PR rtl-optimization/84308
[official-gcc.git] / liboffloadmic / runtime / offload_omp_target.cpp
blob2bcfef5acea629792471d71c236175024a6880f8
1 /*
2 Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
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.
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.
31 #include <omp.h>
32 #include "offload.h"
33 #include "compiler_if_target.h"
35 // OpenMP API
37 void omp_set_default_device(int num) __GOMP_NOTHROW
41 int omp_get_default_device(void) __GOMP_NOTHROW
43 return mic_index;
46 int omp_get_num_devices() __GOMP_NOTHROW
48 return mic_engines_total;
51 // OpenMP 4.5 APIs
53 // COI supports 3-dim multiD transfers
54 #define MAX_ARRAY_RANK 3
56 DLL_LOCAL void omp_target_alloc_target(
57 void *ofld_
60 OFFLOAD ofld = (OFFLOAD) ofld_;
61 VarDesc vars[2] = {0};
62 size_t size;
63 void* memory;
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;
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;
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);
85 DLL_LOCAL void omp_target_free_target(
86 void *ofld_
89 OFFLOAD ofld = (OFFLOAD) ofld_;
90 VarDesc vars[1] = {0};
91 void* memory;
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;
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);
105 DLL_LOCAL void omp_target_memcpy_target(
106 void *ofld_
109 OFFLOAD ofld = (OFFLOAD) ofld_;
110 VarDesc vars[3] = {0};
111 void* dst;
112 void* src;
113 size_t length;
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;
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;
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;
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);
135 OFFLOAD_DEBUG_TRACE(2, "omp_target_memcpy done\n");
136 OFFLOAD_TARGET_LEAVE(ofld);
139 static size_t bytesize_at_this_dimension(
140 size_t element_size,
141 int num_dims,
142 const size_t* dimensions
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;
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
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);
181 } else {
182 memcpy(dst+dst_offsets[0]*element_size,
183 src+src_offsets[0]*element_size,
184 element_size * volume[0]);
188 DLL_LOCAL void omp_target_memcpy_rect_target(
189 void *ofld_
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;
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;
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]);
220 OFFLOAD_DEBUG_TRACE(2, "omp_target_memcpy_rect done\n");
221 OFFLOAD_TARGET_LEAVE(ofld);
224 // End of OpenMP 4.5 APIs
227 // OpenMP API wrappers
229 static void omp_send_int_to_host(
230 void *ofld_,
231 int setting
234 OFFLOAD ofld = (OFFLOAD) ofld_;
235 VarDesc vars[1] = {0};
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;
242 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
243 OFFLOAD_TARGET_LEAVE(ofld);
246 static int omp_get_int_from_host(
247 void *ofld_
250 OFFLOAD ofld = (OFFLOAD) ofld_;
251 VarDesc vars[1] = {0};
252 int setting;
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;
259 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
260 OFFLOAD_TARGET_LEAVE(ofld);
262 return setting;
265 DLL_LOCAL void omp_set_num_threads_lrb(
266 void *ofld
269 int num_threads;
271 num_threads = omp_get_int_from_host(ofld);
272 omp_set_num_threads(num_threads);
275 DLL_LOCAL void omp_get_max_threads_lrb(
276 void *ofld
279 int num_threads;
281 num_threads = omp_get_max_threads();
282 omp_send_int_to_host(ofld, num_threads);
285 DLL_LOCAL void omp_get_num_procs_lrb(
286 void *ofld
289 int num_procs;
291 num_procs = omp_get_num_procs();
292 omp_send_int_to_host(ofld, num_procs);
295 DLL_LOCAL void omp_set_dynamic_lrb(
296 void *ofld
299 int dynamic;
301 dynamic = omp_get_int_from_host(ofld);
302 omp_set_dynamic(dynamic);
305 DLL_LOCAL void omp_get_dynamic_lrb(
306 void *ofld
309 int dynamic;
311 dynamic = omp_get_dynamic();
312 omp_send_int_to_host(ofld, dynamic);
315 DLL_LOCAL void omp_set_nested_lrb(
316 void *ofld
319 int nested;
321 nested = omp_get_int_from_host(ofld);
322 omp_set_nested(nested);
325 DLL_LOCAL void omp_get_nested_lrb(
326 void *ofld
329 int nested;
331 nested = omp_get_nested();
332 omp_send_int_to_host(ofld, nested);
335 DLL_LOCAL void omp_set_schedule_lrb(
336 void *ofld_
339 OFFLOAD ofld = (OFFLOAD) ofld_;
340 VarDesc vars[2] = {0};
341 omp_sched_t kind;
342 int modifier;
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;
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;
354 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
355 omp_set_schedule(kind, modifier);
356 OFFLOAD_TARGET_LEAVE(ofld);
359 DLL_LOCAL void omp_get_schedule_lrb(
360 void *ofld_
363 OFFLOAD ofld = (OFFLOAD) ofld_;
364 VarDesc vars[2] = {0};
365 omp_sched_t kind;
366 int modifier;
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;
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;
378 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
379 omp_get_schedule(&kind, &modifier);
380 OFFLOAD_TARGET_LEAVE(ofld);
383 // lock API functions
385 DLL_LOCAL void omp_init_lock_lrb(
386 void *ofld_
389 OFFLOAD ofld = (OFFLOAD) ofld_;
390 VarDesc vars[1] = {0};
391 omp_lock_target_t lock;
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;
398 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
399 omp_init_lock(&lock.lock);
400 OFFLOAD_TARGET_LEAVE(ofld);
403 DLL_LOCAL void omp_destroy_lock_lrb(
404 void *ofld_
407 OFFLOAD ofld = (OFFLOAD) ofld_;
408 VarDesc vars[1] = {0};
409 omp_lock_target_t lock;
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;
416 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
417 omp_destroy_lock(&lock.lock);
418 OFFLOAD_TARGET_LEAVE(ofld);
421 DLL_LOCAL void omp_set_lock_lrb(
422 void *ofld_
425 OFFLOAD ofld = (OFFLOAD) ofld_;
426 VarDesc vars[1] = {0};
427 omp_lock_target_t lock;
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;
434 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
435 omp_set_lock(&lock.lock);
436 OFFLOAD_TARGET_LEAVE(ofld);
439 DLL_LOCAL void omp_unset_lock_lrb(
440 void *ofld_
443 OFFLOAD ofld = (OFFLOAD) ofld_;
444 VarDesc vars[1] = {0};
445 omp_lock_target_t lock;
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;
452 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
453 omp_unset_lock(&lock.lock);
454 OFFLOAD_TARGET_LEAVE(ofld);
457 DLL_LOCAL void omp_test_lock_lrb(
458 void *ofld_
461 OFFLOAD ofld = (OFFLOAD) ofld_;
462 VarDesc vars[2] = {0};
463 omp_lock_target_t lock;
464 int result;
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;
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;
476 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
477 result = omp_test_lock(&lock.lock);
478 OFFLOAD_TARGET_LEAVE(ofld);
481 // nested lock API functions
483 DLL_LOCAL void omp_init_nest_lock_lrb(
484 void *ofld_
487 OFFLOAD ofld = (OFFLOAD) ofld_;
488 VarDesc vars[1] = {0};
489 omp_nest_lock_target_t lock;
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;
496 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
497 omp_init_nest_lock(&lock.lock);
498 OFFLOAD_TARGET_LEAVE(ofld);
501 DLL_LOCAL void omp_destroy_nest_lock_lrb(
502 void *ofld_
505 OFFLOAD ofld = (OFFLOAD) ofld_;
506 VarDesc vars[1] = {0};
507 omp_nest_lock_target_t lock;
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;
514 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
515 omp_destroy_nest_lock(&lock.lock);
516 OFFLOAD_TARGET_LEAVE(ofld);
519 DLL_LOCAL void omp_set_nest_lock_lrb(
520 void *ofld_
523 OFFLOAD ofld = (OFFLOAD) ofld_;
524 VarDesc vars[1] = {0};
525 omp_nest_lock_target_t lock;
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;
532 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
533 omp_set_nest_lock(&lock.lock);
534 OFFLOAD_TARGET_LEAVE(ofld);
537 DLL_LOCAL void omp_unset_nest_lock_lrb(
538 void *ofld_
541 OFFLOAD ofld = (OFFLOAD) ofld_;
542 VarDesc vars[1] = {0};
543 omp_nest_lock_target_t lock;
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;
550 OFFLOAD_TARGET_ENTER(ofld, 1, vars, NULL);
551 omp_unset_nest_lock(&lock.lock);
552 OFFLOAD_TARGET_LEAVE(ofld);
555 DLL_LOCAL void omp_test_nest_lock_lrb(
556 void *ofld_
559 OFFLOAD ofld = (OFFLOAD) ofld_;
560 VarDesc vars[2] = {0};
561 omp_nest_lock_target_t lock;
562 int result;
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;
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;
574 OFFLOAD_TARGET_ENTER(ofld, 2, vars, NULL);
575 result = omp_test_nest_lock(&lock.lock);
576 OFFLOAD_TARGET_LEAVE(ofld);
579 // Target-side stubs for the host functions (to avoid unresolveds)
580 // These are needed for the offloadm table
582 void omp_set_num_threads_target(
583 TARGET_TYPE target_type,
584 int target_number,
585 int num_threads
590 int omp_get_max_threads_target(
591 TARGET_TYPE target_type,
592 int target_number
595 return 0;
598 int omp_get_num_procs_target(
599 TARGET_TYPE target_type,
600 int target_number
603 return 0;
606 void omp_set_dynamic_target(
607 TARGET_TYPE target_type,
608 int target_number,
609 int num_threads
614 int omp_get_dynamic_target(
615 TARGET_TYPE target_type,
616 int target_number
619 return 0;
622 void omp_set_nested_target(
623 TARGET_TYPE target_type,
624 int target_number,
625 int num_threads
630 int omp_get_nested_target(
631 TARGET_TYPE target_type,
632 int target_number
635 return 0;
638 void omp_set_schedule_target(
639 TARGET_TYPE target_type,
640 int target_number,
641 omp_sched_t kind,
642 int modifier
647 void omp_get_schedule_target(
648 TARGET_TYPE target_type,
649 int target_number,
650 omp_sched_t *kind,
651 int *modifier
656 void omp_init_lock_target(
657 TARGET_TYPE target_type,
658 int target_number,
659 omp_lock_target_t *lock
664 void omp_destroy_lock_target(
665 TARGET_TYPE target_type,
666 int target_number,
667 omp_lock_target_t *lock
672 void omp_set_lock_target(
673 TARGET_TYPE target_type,
674 int target_number,
675 omp_lock_target_t *lock
680 void omp_unset_lock_target(
681 TARGET_TYPE target_type,
682 int target_number,
683 omp_lock_target_t *lock
688 int omp_test_lock_target(
689 TARGET_TYPE target_type,
690 int target_number,
691 omp_lock_target_t *lock
694 return 0;
697 void omp_init_nest_lock_target(
698 TARGET_TYPE target_type,
699 int target_number,
700 omp_nest_lock_target_t *lock
705 void omp_destroy_nest_lock_target(
706 TARGET_TYPE target_type,
707 int target_number,
708 omp_nest_lock_target_t *lock
713 void omp_set_nest_lock_target(
714 TARGET_TYPE target_type,
715 int target_number,
716 omp_nest_lock_target_t *lock
721 void omp_unset_nest_lock_target(
722 TARGET_TYPE target_type,
723 int target_number,
724 omp_nest_lock_target_t *lock
729 int omp_test_nest_lock_target(
730 TARGET_TYPE target_type,
731 int target_number,
732 omp_nest_lock_target_t *lock
735 return 0;