Compare commits

..
278 Commits
Author SHA1 Message Date
Jon Chesterfield 56d941a8ce [libomptarget][nfc] Make interface.h target independent
Summary:
[libomptarget][nfc] Make interface.h target independent

Move interface.h under a top level include directory.
Remove #includes to avoid the interface depending on the implementation.

Reviewers: ABataev, jdoerfert, grokos, ronlieb, RaviNarayanaswamy

Reviewed By: jdoerfert

Subscribers: mgorny, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D68615

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@374919 91177308-0d34-0410-b5e6-96231b3b80d8
2019-10-15 17:15:26 +00:00
David Carlier cb6f3c46a8 [OpenMP] Enable thread affinity on FreeBSD
Reviewers: chandlerc, jlpeyton, jdoerfert, dim

Reviewed-By: dim

Differential Revision: https://reviews.llvm.org/D68580

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@374118 91177308-0d34-0410-b5e6-96231b3b80d8
2019-10-08 21:25:30 +00:00
Andrey Churbanov ace8505db1 Don't assume Type from readelf -d has parentheses
Patch by jbeich (Jan Beich)

Differential Revision: https://reviews.llvm.org/D68053

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@374038 91177308-0d34-0410-b5e6-96231b3b80d8
2019-10-08 12:39:04 +00:00
Andrey Churbanov 9dfddd6912 Don't link libm with -Wl,--as-needed on FreeBSD
Patch by jbeich (Jan Beich)

Differential Revision: https://reviews.llvm.org/D68051

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@374037 91177308-0d34-0410-b5e6-96231b3b80d8
2019-10-08 12:23:25 +00:00
Jon Chesterfield 731769fe89 [libomptarget][nfc] Update remaining uint32 to use lanemask_t
Summary:
[libomptarget][nfc] Update remaining uint32 to use lanemask_t

Update a few functions in the API to use lanemask_t instead of i32. NFC for
nvptx. Also update the ActiveThreads type in DataSharingStateTy.
This removes a lot of #ifdef from the downsteam amdgcn implementation.

Reviewers: ABataev, jdoerfert, grokos, ronlieb, RaviNarayanaswamy

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D68513

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@373806 91177308-0d34-0410-b5e6-96231b3b80d8
2019-10-04 22:30:28 +00:00
Jon Chesterfield 3bdcaec89a Use named constant to indicate all lanes, to handle 32 and 64 wide architectures
Summary: Use named constant to indicate all lanes, to handle 32 and 64 wide architectures

Reviewers: ABataev, jdoerfert, grokos, ronlieb

Reviewed By: grokos

Subscribers: ronlieb, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D68369

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@373793 91177308-0d34-0410-b5e6-96231b3b80d8
2019-10-04 21:39:22 +00:00
David Carlier 85e24591e4 [OpenMP] FreeBSD address check if mapped more native
/proc unless Linux layer compatibility is activated for CentOS is activated is not present
thus relying on a more native for checking the address.

Reviewers: Hahnfeld, kongyl, jdoerfert, jlpeyton, AndreyChurbanov, emaster, dim

Reviewed By: Hahnfeld

Differential Revision: https://reviews.llvm.org/D67326

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@373152 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-28 19:01:59 +00:00
Sergey Dmitriev dbb024cf94 [Clang][OpenMP Offload] Create start/end symbols for the offloading entry table with a help of a linker
Linker automatically provides __start_<section name> and __stop_<section name> symbols to satisfy unresolved references if <section name> is representable as a C identifier (see https://sourceware.org/binutils/docs/ld/Input-Section-Example.html for details). These symbols indicate the start address and end address of the output section respectively. Therefore, renaming OpenMP offload entries section name from ".omp.offloading_entries" to "omp_offloading_entries" to use this feature.

This is the first part of the patch for eliminating OpenMP linker script (please see https://reviews.llvm.org/D64943).

Differential Revision: https://reviews.llvm.org/D68070

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@373118 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-27 20:00:51 +00:00
Andrey Churbanov 2cb5d49f71 fixed test: eliminated race condition which might cause deadlock
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@372887 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-25 15:25:52 +00:00
Andrey Churbanov 66ddc2110a Enable tasks dependencies hashmaps resizing.
Patch by viroulep (Philippe Virouleau)

Differential Revision: https://reviews.llvm.org/D67447


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@372879 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-25 14:40:19 +00:00
Jonas Hahnfeld 2b135c5afc [OpenMP] Change initialization of __kmp_global
There's no need to initialize variables with static storage duration
because they're implicitly initialized to zero. See
https://en.cppreference.com/w/c/language/initialization#Implicit_initialization

I think that's already relied upon because the supplied 0 only sets
'kmp_time_global_t g_time;' in 'struct kmp_base_global'. The other fields
are not set in the code, but implicitly initialized by the compiler.

Differential Revision: https://reviews.llvm.org/D66292

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370943 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-04 17:47:37 +00:00
Alexey Bataev b93e8ad893 [OPENMP][NVPTX]Fix parallel level counter in non-SPMD mode.
Summary:
In non-SPMD mode we may end up with the divergent threads when trying to
increment/decrement parallel level counter. It may lead to incorrect
calculations of the parallel level and wrong results when threads are
divergent. We need to reconverge the threads before trying to modify the
parallel level counter.

Reviewers: grokos, jdoerfert

Subscribers: guansong, openmp-commits, caomhin, kkwli0

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66802

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370803 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-03 18:11:50 +00:00
Jon Chesterfield 537de38cfe [libomptarget] Refactor activemask macro to inline function
Summary:
[libomptarget] Refactor activemask macro to inline function
See also abandoned D66846, split into this diff and others.

Reviewers: jdoerfert, ABataev, grokos, ronlieb, gregrodgers

Reviewed By: jdoerfert, ABataev

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66851

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370781 91177308-0d34-0410-b5e6-96231b3b80d8
2019-09-03 16:31:30 +00:00
Jon Chesterfield 1fe4d6217e Use target_impl functions to replace more inline asm
Summary:
Use target_impl functions to replace more inline asm
Follow on from D65836. Removes remaining asm shuffles and lanemask accessors
Also changes the types of target_impl bitwise functions to unsigned.

Reviewers: jdoerfert, ABataev, grokos, Hahnfeld, gregrodgers, ronlieb, hfinkel

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66809

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370216 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-28 15:04:06 +00:00
Jon Chesterfield ee03160612 [libomptarget] Refactor syncthreads macro to inline function
Summary:
[libomptarget] Refactor syncthreads macro to inline function
See also abandoned D66846, split into this diff and others.

Rev 2 of D66855

Reviewers: jdoerfert, ABataev, grokos, ronlieb, gregrodgers

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66861

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370210 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-28 14:22:35 +00:00
Jon Chesterfield 7ed5372fe0 [libomptarget] Refactor syncwarp macro to inline function
Summary:
[libomptarget] Refactor syncwarp macro to inline function
See also abandoned D66846, split into this diff and others.

Reviewers: jdoerfert, ABataev, grokos, ronlieb, gregrodgers

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66857

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370149 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-28 02:02:53 +00:00
Jon Chesterfield bae5e5989e Fix build break due to close brace lost in merge
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370148 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-28 01:56:26 +00:00
Jon Chesterfield 77d31c11e8 [libomptarget] Refactor shfl_down_sync macro to inline function
Summary:
[libomptarget] Refactor shfl_down_sync macro to inline function
See also abandoned D66846, split into this diff and others.

Reviewers: jdoerfert, ABataev, grokos, ronlieb, gregrodgers

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66853

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370146 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-28 01:47:41 +00:00
Jon Chesterfield bfca7f70c5 [libomptarget] Refactor shfl_sync macro to inline function
Summary:
[libomptarget] Refactor shfl_sync macro to inline function
See also abandoned D66846, split into this diff and others.

Reviewers: jdoerfert, ABataev, grokos, ronlieb, gregrodgers

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66852

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@370144 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-28 01:31:04 +00:00
Alexey Bataev ad72f5e57b [OPENMP][NVPTX]Add __kmpc_syncwarp(int32_t) function.
Summary:
Added function void __kmpc_syncwarp(int32_t) to expose it to the
compiler. It is required to fix the problem with the critical regions in
Cuda9.0+. We cannot use barrier in the critical region, but still need
to reconverge the threads in the warp after. This function allows to do
this.

Reviewers: grokos, jdoerfert

Subscribers: guansong, openmp-commits, kkwli0, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D66672

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@369933 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-26 17:32:45 +00:00
Alexey Bataev cd9405f3b9 [OPENMP][NVPTX]Use __syncwarp() to reconverge the threads.
Summary:
In Cuda 9.0 it is not guaranteed that threads in the warps are
convergent. We need to use __syncwarp() function to reconverge
the threads and to guarantee the memory ordering among threads in the
warps.
This is the first patch to fix the problem with the test
libomptarget/deviceRTLs/nvptx/src/sync.cu on Cuda9+.
This patch just replaces calls to __shfl_sync() function with the call
of __syncwarp() function where we need to reconverge the threads when we
try to modify the value of the parallel level counter.

Reviewers: grokos

Subscribers: guansong, jfb, jdoerfert, caomhin, kkwli0, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D65013

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@369796 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-23 18:34:48 +00:00
Jonathan Peyton 3f4c51a258 Force honoring nthreads-var and thread-limit-var inside teams construct on host
This patch fixes https://bugs.llvm.org/show_bug.cgi?id=42906, via adding
adjustment of number of threads on enter to the teams construct on host
according to user settings. This allows to pass checks and avoid assertions
at time of team of threads creation.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D66351


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@369430 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-20 19:39:17 +00:00
Jonas Hahnfeld 3eae253b1a [OpenMP] Enable warning about "implicit fallthrough"
Fix last warned location in ittnotify_static.cpp using the defined
macro KMP_FALLTHROUGH().

Differential Revision: https://reviews.llvm.org/D65871

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@369003 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-15 13:26:55 +00:00
Jonas Hahnfeld 7875131e8d [OpenMP] Remove 'unnecessary parentheses'
The variables in kmp_lock.cpp are really arrays of function pointers
that return void or int, not pointers to functions that return void*
or int*. The other changes are only cosmetic.

Differential Revision: https://reviews.llvm.org/D65870

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@369002 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-15 13:26:41 +00:00
Jonas Hahnfeld b0cb65c508 [OMPT] Resolve warnings because of ints in if conditions
The implementation status can only be one of
ompt_event_UNIMPLEMENTED = ompt_set_never = 1
ompt_event_MAY_ALWAYS = ompt_set_always = 5

In both cases, the condition was already true, so just remove
the check.

Differential Revision: https://reviews.llvm.org/D65869

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@369001 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-15 13:26:29 +00:00
Jonas Hahnfeld 04b98c1875 [OpenMP] Turn on -Wall compiler warnings by default
Instead, maintain a list of disabled options to still build libomp and
libomptarget without warnings. This includes -Wno-error and -Wno-pedantic
to silence warnings that LLVM enables when building in-tree.

I tested the following compilers:
 * Clang 6.0, 7.0, 8.0
 * GCC 4.8.5 (CentOS 7), GCC 6, 7, 8, 9
 * Intel Compiler 16, 17, 18, 19

RFC thread on openmp-dev mailing list:
http://lists.llvm.org/pipermail/openmp-dev/2019-August/002668.html

Differential Revision: https://reviews.llvm.org/D65867

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368999 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-15 13:11:50 +00:00
Jon Chesterfield 923dcc5544 Factor architecture dependent code out of loop.cu
Summary:
[libomptarget] Factor architecture dependent code out of loop.cu

Related to the patch series starting D64217. Added subscribers to said series as reviewers. This effort is smaller in scope.

This patch factors out just enough architecture dependent code from loop.cu to allow the same source to be used with amdgcn, given a different target_impl.h. Testing is that the same bitcode (modulo variable names) is generated for libomptarget before and after the refactor, for nvptx and the out of tree amdgcn.

Reviewers: jdoerfert, ABataev, bollu, jfb, tra, grokos, Hahnfeld, guansong, xtian, gregrodgers, ronlieb, hfinkel, gtbercea, guraypp, arpith-jacob

Reviewed By: jdoerfert, ABataev

Subscribers: dexonsmith, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D65836

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368751 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-13 21:41:47 +00:00
Andrey Churbanov ee9c0c5007 Cleanup unused variable.
This patch fixes problem raised in post-review comments of the
https://reviews.llvm.org/D65285. Developers of ittnotify confirmed
that dll_path_ptr field of the __itt_global structure is never used
by ittnotify library, so it is safe to remove the dll_path array.

Differential Revision: https://reviews.llvm.org/D65885


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368559 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-12 12:37:30 +00:00
Gheorghe-Teodor Bercea dabebaf3ab [OpenMP][libomptarget] Add support for close map modifier
Summary:
This patch adds support for the close map modifier.

The close map modifier will overwrite the unified shared memory requirement and create a device copy of the data.

Reviewers: ABataev, Hahnfeld, caomhin, grokos, jdoerfert, AlexEichenberger

Reviewed By: Hahnfeld, AlexEichenberger

Subscribers: guansong, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D65340

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368488 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-09 21:32:57 +00:00
Jonas Hahnfeld 9ea8071852 [libomptarget] Remove duplicate RTLRequiresFlags per device
We have one global RTLs.RequiresFlags, I don't see a need to make a
copy per device that the runtime manages. This was problematic anyway
because the copy happened during the first __tgt_register_lib(). This
made it impossible to call __tgt_register_requires() from normal user
funtions for testing.
Hence, this change also fixes unified_shared_memory/shared_update.c for
older versions of Clang that don't call __tgt_register_requires() before
__tgt_register_lib().

Differential Revision: https://reviews.llvm.org/D66019

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368465 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-09 19:20:39 +00:00
Gheorghe-Teodor Bercea 3654abe1c4 [OpenMP][libomptarget] Add support for unified memory for regular maps
Summary:
This patch adds support for using unified memory in the case of regular maps that happen when a target region is offloaded to the device.

For cases where only a single version of the data is required then the host address can be used. When variables need to be privatized in any way or globalized, then the copy to the device is still required for correctness.

Reviewers: ABataev, jdoerfert, Hahnfeld, AlexEichenberger, caomhin, grokos

Reviewed By: Hahnfeld

Subscribers: mgorny, guansong, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D65001

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368192 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-07 17:29:45 +00:00
Jon Chesterfield 2535f2b254 Use forceinline. Necessary for nvcc to inline small functions within the bitcode library
Summary:
[libomptarget] Use forceinline. Necessary for nvcc to inline small functions within the bitcode library
Suggested in D65836

Reviewers: ABataev, jdoerfert, grokos, gregrodgers

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D65876

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368177 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-07 15:24:12 +00:00
Alexey Bataev c8294f02f9 [OPENMP][OFFLOADING]Fix the test, NFC.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@368068 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-06 18:13:39 +00:00
Jonathan Peyton 3c7e9228ca [OpenMP] Add support for GOMP_*_nonmonotonic_* functions
Patch by Isuru Fernando

Differential Revision: https://reviews.llvm.org/D65714


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367949 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-05 23:23:52 +00:00
Hansang Bae 6a2cf6907c [OpenMP] Fix broken build due to new OMPT tests
New OMPT tests with teams construct should be disabled for GCC as it
emits code with a GOMP entry not supported in the LLVM runtime.

Differential Revision: https://reviews.llvm.org/D65757


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367939 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-05 21:46:13 +00:00
Michael Kruse 64bfa8497f [libomptarget] Harmonize emitting CUDA errors and general debug messages.
Ensures that CUDA fail reasons (such as "No CUDA-capable device detected")
are printed together with libomptarget's debug message
(e.g. "Error when setting CUDA context"). Previously, the former was
printed only in CMAKE_BUILD_TYPE=Debug builds while the latter was
enabled by LIBOMPTARGET_ENABLE_DEBUG.

With this change, also only call cuGetErrorString when the error will be
printed.

Suggested-by: Ye Luo <xw111luoye@gmail.com>

Differential Revision: https://reviews.llvm.org/D65687

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367910 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-05 19:12:10 +00:00
Michael Kruse e8bd614a37 [OpenMP 5.0] libomptarget interface for declare mapper functions.
This patch implements the libomptarget runtime interface for OpenMP 5.0
declare mapper functions. The declare mapper functions generated by
Clang will call them to complete the mapping of members.
kmpc_mapper_num_components gets the current number of components for a
user-defined mapper; kmpc_push_mapper_component pushes back one
component for a user-defined mapper.

The design slides can be found at
https://github.com/lingda-li/public-sharing/blob/master/mapper_runtime_design.pptx

Patch by Lingda Li <lildmh@gmail.com>

Differential Revision: https://reviews.llvm.org/D60972

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367772 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-04 04:18:28 +00:00
Hansang Bae 716f6ba727 Add OMPT support for teams construct
This change adds OMPT support for events from teams construct.

Differential Revision: https://reviews.llvm.org/D64025


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367746 91177308-0d34-0410-b5e6-96231b3b80d8
2019-08-03 02:38:53 +00:00
Jonas Hahnfeld 6cbafacdcf [OpenMP] Rename last file to cpp and remove LIBOMP_CFLAGS
All other files are already C++ and the build system has always
passed '-x c++' for C files, effectively compiling them as C++.

To stay warning free we need one fix in ittnotify_static.{c,cpp}:
The variable dll_path can be written to, so it must not be const.
GCC complained with -Wcast-qual and I think it's right.

Differential Revision: https://reviews.llvm.org/D65285

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367343 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-30 18:37:28 +00:00
Yi Kong 34b2830c83 [openmp] Workaround bug in old Android pthread_attr_setstacksize
Round the stack size to a multiple of the page size. Older versions of
Android (until KitKat) would fail pthread_attr_setstacksize with
EINVAL if the stack size was not a multiple of the page size.

Patch by Dan Albert <danalbert@google.com>.

Test: Build, copied into the NDK, passed openmp test on ICS.
Bug: https://github.com/android-ndk/ndk/issues/9

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367070 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-25 22:29:55 +00:00
Jonas Hahnfeld ca7d371ddf [OpenMP] Fix build of stubs library, NFC.
Both Clang and GCC complained that they cannot initialize a return
object of type 'kmp_proc_bind_t' with an 'int'. While at it, also
fix a warning about missing parentheses thrown by Clang.

Differential Revision: https://reviews.llvm.org/D65284

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367041 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-25 17:51:24 +00:00
Alexey Bataev b9b98019a0 [OPENMP][NVPTX]Perform memory flush if number of threads to sync is 1 or less.
Summary:
According to the OpenMP standard, barrier operation must perform
implicit flush operation. Currently, if there is only one thread in the
team, barrier does not flush the memory. Patch fixes this problem.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D62398

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367024 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-25 15:02:28 +00:00
Jonas Hahnfeld 57b2fafae6 [OpenMP] RISCV64 port
This is a port of libomp for the RISC-V 64-bit Linux target.

We have tested this port on a HiFive Unleashed development board
using a downstream LLVM that has support for the missing bits in
upstream. As of now, all tests are passing, including OMPT.

Patch by Ferran Pallarès!

Differential Revision: https://reviews.llvm.org/D59880

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@367021 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-25 14:36:20 +00:00
Jonas Hahnfeld b840a856c2 [libomptarget] Handle offload policy in push_tripcount
If the first target region in a program calls the push_tripcount
function, libomptarget didn't handle the offload policy correctly.
This could lead to unexpected error messages as seen in
http://lists.llvm.org/pipermail/openmp-dev/2019-June/002561.html

To solve this, add a check calling IsOffloadDisabled() as all other
entry points already do. If this method returns false, libomptarget
is effectively disabled.

Differential Revision: https://reviews.llvm.org/D64626

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366810 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-23 14:20:48 +00:00
Jonas Hahnfeld 9ad60c0ccd [OMPT] Cleanup reset of exit_frame pointer
This is done at call-site and does not need to be handled in
__kmp_invoke_microtask. It was already absent from the x86
and x86_64 assembly, this patch removes it from the generic
implementation in z_Linux_util.cpp and adds documentation for
AArch64 and PPC64 that it's actually not needed. I can't test
on these architectures, so I don't want to change the code just
because it looks right :)

While at it, rename some variables for consistency and add a
check in test/ompt/parallel/normal.c that the pointer was reset
before entering the barrier.

Differential Revision: https://reviews.llvm.org/D64442

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366721 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-22 18:46:02 +00:00
Jonas Hahnfeld 8dabfbaf51 Delete empty file
This is a left-over from r356288 which was reviewed in D58989.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366716 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-22 18:11:06 +00:00
Alexey Bataev b0376454fa [OpenMP][libomptarget] Suppress C++ 11 related warnings when building libomptarget-nvptx bitcode library, by Doru Bercea.
Summary: Pass -std=c++11 flag to compiler to suppress C++ 11 related warnings when building NVPTX bitcode library.

Reviewers: ABataev, caomhin, Hahnfeld

Reviewed By: ABataev, Hahnfeld

Subscribers: jdoerfert, Hahnfeld, jholewinski, mgorny, guansong, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D55772

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366438 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-18 13:54:01 +00:00
Ron Lieberman c1b1ef1c00 [OPENMP] Resolve lost LoopTripCnt for subsequent loops in same thread.
Remove loopTripCnt from threaded device stack after consuming it.
Added a libomptarget DP message to aid in future debugging and to
validate the added testcase, which only runs in Debug build.

Differential Revision: https://reviews.llvm.org/D64808


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366349 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-17 17:07:52 +00:00
Jonathan Peyton 07f4283e71 Remove REQUIRES OMP spec version within lit tests
This is a follow up patch to D64534 (r365963) which removed all OMP
spec versioning within the OpenMP runtime codebase.  This patch removes
REQUIRES: openmp-x.y lines from lit tests.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366341 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-17 15:41:00 +00:00
Jonas Hahnfeld cff3557e55 [OpenMP] Move header inclusion out of 'extern "C"'
This leads to problems when compiling C++ code with libc++ for Nvidia GPUs
because Clang now uses wrappers for math functions that might include
C++ templates not allowed in 'extern "C"'.

Differentiel Revision: https://reviews.llvm.org/D64625

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366229 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-16 17:16:43 +00:00
Alexey Bataev 0519a2c6b2 [OPENMP][NVPTX]Fixed checks for cuda versions.
Summary:
We used CUDART_VERSION macro to check for the installed cuda version
but this macro is defined in cuda_runtime_api.h, which is not used by
project. Better to use CUDA_VERSION macro, which is defined in cuda.h.
Also, added the check if this macro is defined. If macro is undefined,
there is something wrong with the cuda configuration and we should not
continue the compilation.
This also fixes problems with runtime building in cuda 10+.

Reviewers: grokos

Subscribers: guansong, jdoerfert, caomhin, kkwli0, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D64648

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366224 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-16 16:07:10 +00:00
Alexey Bataev 946967528b [OPENMP]Fix threadid in __kmpc_omp_taskwait call for dependent target calls.
Summary:
We used to call __kmpc_omp_taskwait function with global threadid set to
0. It may crash the application at the runtime if the thread executing
 target region is not a master thread.

Reviewers: grokos, kkwli0

Subscribers: guansong, jdoerfert, caomhin, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D64571

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@366220 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-16 15:51:32 +00:00
Jonathan Peyton d4b114904a [OpenMP] Remove OMP spec versioning
Remove all older OMP spec versioning from the runtime and build system.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D64534


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@365963 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-12 21:45:36 +00:00
Jonas Hahnfeld bb2634a97e [libomptarget] Fix typos and grammar in error messages, NFC.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@365890 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-12 10:21:55 +00:00
Jonas Hahnfeld 8e626ba79d [libomptarget-nvptx] Remove dead functions
These entry points are never called by Clang trunk nor clang-ykt. If
XL doesn't use them either, they can finally go away.

Differential Revision: https://reviews.llvm.org/D52700

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@365817 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-11 20:12:51 +00:00
Andrey Churbanov 201ba9ed4c NFC: fixed typo #ifdef --> #if to allow macro set to 0 work correctly
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@365642 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-10 15:09:37 +00:00
Alexey Bataev 3a22f66a9b [OPENMP]Rename loopTripCnt member data to LoopTripCnt, NFC.
Rename variable to follow LLVM coding standard.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@365368 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-08 18:45:48 +00:00
Alexey Bataev 0b1328156a [OPENMP]Make __kmpc_push_tripcount thread safe.
Summary:
__kmpc_push_tripcount function is not thread safe and may lead to data
race when the target regions are executed in parallel threads. The patch
makes loopTripCnt counter thread aware and stores the tripcount value
per thread in the map. Access to map is guarded by mutex to prevent
data race in the map itself.
Test is for NVPTX target because it does not work correctly on the
host. Seems to me, there is a problem in libomp with target regions in
the parallel threads.

Reviewers: grokos

Subscribers: guansong, jfb, jdoerfert, openmp-commits, kkwli0, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D64080

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@365332 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-08 15:30:23 +00:00
Andrey Churbanov bbbee1dd60 Create a runtime option to disable task throttling.
Patch by viroulep (Philippe Virouleau)

Differential Revision: https://reviews.llvm.org/D63196


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@364934 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-02 15:10:20 +00:00
Andrey Churbanov f9ad1a04db Cleanup of unused code
Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D63891


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@364925 91177308-0d34-0410-b5e6-96231b3b80d8
2019-07-02 13:45:40 +00:00
Alexey Bataev a31ae2e44a [OPENMP][NVPTX]Relax flush directive.
Summary:
According to the OpenMP standard, flush  makes a thread’s temporary view of memory consistent with memory and enforces an order on the memory operations of the variables explicitly specified or implied.

According to the Cuda toolkit documentation (https://docs.nvidia.com/cuda/archive/8.0/cuda-c-programming-guide/index.html#memory-fence-functions), __threadfence() functions provides required functionality.

__threadfence_system() also provides required functionality, but it also
includes some extra functionality, like synchronization of page-locked
host memory, synchronization for the host, etc. It is not required per
the standard and we can use more relaxed version of memory fence
operation.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jfb, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D62397

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@364572 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-27 18:33:09 +00:00
Andrey Churbanov 0afc673b17 Fixed memory use-after-free problem.
Bug reported in https://bugs.llvm.org/show_bug.cgi?id=42269.
Freeing of the contention group (CG) stucture by master thread looks wrong,
because workers can leave the CG later on. Intead the freeing
is now done by the last thread leaving the CG.

Differential Revision: https://reviews.llvm.org/D63599


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@364456 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-26 18:11:26 +00:00
Gheorghe-Teodor Bercea 4df92eda05 [OpenMP][libomptarget] Add support for declare target to clause under unified memory
Summary:
This patch adds support for handling variables under the:

```
#pragma omp declare target to()
```

clause when the 

```
#pragma omp requires unified_shared_memory
```

is used.

The address of the host variable is copied into the device pointer just like for the declare target link case.

Reviewers: ABataev, caomhin, grokos, AlexEichenberger

Reviewed By: grokos

Subscribers: jcownie, guansong, jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D63106

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@363825 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-19 15:48:10 +00:00
Alexey Bataev 79d5d6d37a [OPENMP][CUDA]Use __syncthreads when compiled by nvcc and clang >= 9.0.
Summary:
The problems with __syncthreads() were fixed in clang >= 9.0 and the
original __syncthreads() can be used instead of the ptx instruction.

Reviewers: grokos

Subscribers: guansong, jdoerfert, openmp-commits, kkwli0, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D63515

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@363807 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-19 14:20:34 +00:00
Andrey Churbanov 3f381f546e New implementation of OpenMP 5.0 detached tasks.
Patch by Alex Duran

Differential Revision: https://reviews.llvm.org/D62485


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@363799 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-19 13:23:28 +00:00
Gheorghe-Teodor Bercea e9791d7f37 [OpenMP] Add task alloc function
Summary: Add the target task allocation function to the interface.

Reviewers: ABataev, AlexEichenberger, caomhin, jlpeyton, AndreyChurbanov, RaviNarayanaswamy, hbae

Reviewed By: AlexEichenberger, hbae

Subscribers: hbae, RaviNarayanaswamy, cfe-commits, Hahnfeld, guansong, jdoerfert, openmp-commits

Tags: #openmp, #clang

Differential Revision: https://reviews.llvm.org/D63010

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@363449 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-14 20:15:15 +00:00
Andrey Churbanov 402c7439d7 Added propagation of not big initial stack size of master thread to workers.
Currently implemented only for non-Windows 64-bit platforms.

Differential Revision: https://reviews.llvm.org/D62488


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@362618 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-05 16:14:47 +00:00
Gheorghe-Teodor Bercea dba741d61d [OpenMP][libomptarget] Enable usage of unified memory for declare target link variables
Summary: This patch enables the usage of a host variable on the device for declare target link variables when unified memory is available.

Reviewers: ABataev, caomhin, grokos

Reviewed By: grokos

Subscribers: Hahnfeld, guansong, jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60884

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@362505 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-04 15:05:53 +00:00
Andrey Churbanov 6973da5c32 Fixed build warning with -DLIBOMP_USE_HWLOC=1
Made type of depth of hwloc object to correapond with
change from unsigned in hwloc 1,x to int in hwloc 2.x.
This eliminates the warning on signed-unsigned comparison.

Differential Revision: https://reviews.llvm.org/D62332


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@362401 91177308-0d34-0410-b5e6-96231b3b80d8
2019-06-03 14:21:59 +00:00
Hansang Bae 74db2a4213 Fix OMP_TARGET_OFFLOAD parsing
Current parsing allows trailing string after the permitted value,
MANDATORY|DISABLED|DEFAULT -- e.g., "mandatorynot" is also recognized
as "MANDATORY". Such cases should be recognized as incorrect/unknown
value.

Differential Revision: https://reviews.llvm.org/D62431


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@362125 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-30 18:35:07 +00:00
Hansang Bae 48eeef98d8 Add checks before pointer dereferencing
This change adds checks before dereferencing a pointer returned from a
function.

Differential Revision: https://reviews.llvm.org/D62224


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@362111 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-30 16:32:20 +00:00
Michal Gorny 93fe5cefbd [openmp] [test] Skip kernel-breaking tests on NetBSD
The omp_taskloop_num_tasks and omp_taskwait have deadlooped
on the NetBSD buildbot previously, practically hanging the host running
it.  Disable them until we can find a good solution, or make the kernel
less fragile.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361825 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-28 14:10:47 +00:00
Alexey Bataev 34def82866 Revert "[OPENMP][NVPTX]Fix barriers and parallel level counters, NFC."
This reverts commit r361421 to split the patch into 3 parts.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361638 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-24 14:06:47 +00:00
Alexey Bataev 926938a039 [OPENMP][NVPTX]Fix barriers and parallel level counters, NFC.
Summary:
Parallel level counter should be volatile to prevent some dangerous
optimiations by the ptxas. Otherwise, ptxas optimizations lead to
undefined behaviour in some cases.
Also, use __threadfence() for #pragma omp flush and if the barrier
should not be used (we have only one thread in the team), still perform
flush operation since the standard requires implicit flush when
executing barriers.

Reviewers: gtbercea, kkwli0, grokos

Subscribers: guansong, jfb, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D62199

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361421 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-22 19:50:32 +00:00
Andrey Churbanov f8e8d598bf Fixed third issue reported in https://bugs.llvm.org/show_bug.cgi?id=41584.
Removed wrong debug assertion.

Differential Revision: https://reviews.llvm.org/D62251


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361408 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-22 16:48:05 +00:00
Jonathan Peyton 7481323078 [OpenMP] Add implementation to two OMPT API routines
This change adds implementation to ompt_finalize_tool() and
ompt_get_task_memory().

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D61657


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361309 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-21 20:51:05 +00:00
Gheorghe-Teodor Bercea 9994ae3c1c [OpenMP][libomptarget] Enable requires flags for target libraries.
Summary:
Target link variables are currently implemented by creating a copy of the variables on the device side and unified memory never gets exploited.

When the prgram uses the:

```
#pragma omp requires unified_shared_memory
```

directive in conjunction with a declare target link, the linked variable is no longer allocated on the device and the host version is used instead.

This behavior is overridden by performing an explicit mapping.

A Clang side patch is required.

Reviewers: ABataev, AlexEichenberger, grokos, Hahnfeld

Reviewed By: AlexEichenberger, grokos, Hahnfeld

Subscribers: Hahnfeld, jfb, guansong, jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60223

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361294 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-21 19:35:02 +00:00
Joachim Protze 665d5c5112 [OpenMP][OMPT] Fix locking testcases for 32 bit architectures
https://reviews.llvm.org/D58454 did not fix the problem for a typical use
case of building LLVM with gcc or icc and then testing with the newly built
clang compiler.
The compilers do not agree on how to extend a 32-bit pointer to uint64, so
make the pointer unsigned first, before adjusting the size.

Patch by Joachim Protze

Differential Revision: https://reviews.llvm.org/D58506

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361158 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-20 14:21:42 +00:00
Joachim Protze dac3432cdb [OMPT] Handling of the events of initial-task-begin and initial-task-end
OpenMP 5.0 says that the callback for the events initial-task-begin and
initial-task-end has to be ompt_callback_implicit_task.

Patch by Tim Cramer

Differential Revision: https://reviews.llvm.org/D58776

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@361157 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-20 14:21:36 +00:00
Andrey Churbanov ba56714719 Fixed second issue reported in https://bugs.llvm.org/show_bug.cgi?id=41584.
Added synchronization for possible concurrent initialization of mutexes
by multiple threads. The need of synchronization caused by commit r357927
which added the use of mutexes at threads movement to/from common pool
(earlier the mutexes were used only at suspend/resume).

Patch by Johnny Peyton.

Differential Revision: https://reviews.llvm.org/D61995


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360919 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-16 17:52:53 +00:00
Paul Osmialowski 9a0d0f00e9 Fix hwloc topology traversal code unable to handle situation where L2 cache is common for the packages
Currently cores within package that share the same L2 cache are grouped together.
The current logic behind this assumes that the L2 cache is always at deeper
(or the same) level than the package itself. In case when L2 cache is common
for all packages (and the packages are at deeper level than L2 cache) the whole of
the further topology discovery fails to find any computational units resulting in
following assertion:

Assertion failure at kmp_affinity.cpp(715): nActiveThreads == __kmp_avail_proc.
OMP: Error #13: Assertion failure at kmp_affinity.cpp(715).

This patch adds a bit of a logic that prevents such situation from occurring.

Differential Revision: https://reviews.llvm.org/D61796



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360890 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-16 13:16:24 +00:00
Andrey Churbanov a86b5e4738 Fixed https://bugs.llvm.org/show_bug.cgi?id=41584.
Removed unconditional and unsafe decrement of counter 
of active threads in pool at shutdown time.

Differential Revision: https://reviews.llvm.org/D61944


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360784 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-15 16:53:45 +00:00
Andrey Churbanov 0a3b7b60f6 Introduce new OpenMP 5.0 depend object type.
The implementation should be done by compiler, user can only declare
objects of this type and use them in OpenMP directives.

Differential Revision: https://reviews.llvm.org/D61860


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360774 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-15 13:45:36 +00:00
Eli Friedman c1985baed2 [OpenMP][AArch64] Fix compile with LLVM trunk.
The code is currently using the ambiguous instruction
"sub sp, sp, w9, lsl #4". The ARM reference manual says this isn't
valid, and it's not clear whether it's supposed to mean uxtw or uxtx.

It doesn't matter which instruction we use here, since the high
bits of the operand are zero anyway, so I arbitrarily choose uxtw, to
preserve the register name.

See https://reviews.llvm.org/D60840 for the LLVM patch.

Differential Revision: https://reviews.llvm.org/D61770



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360711 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-14 21:44:54 +00:00
Andrey Churbanov 8db7163070 fixed typo made by commit r360595
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360602 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-13 17:04:32 +00:00
Andrey Churbanov fe501ad8d1 Fixed creation of aliases in Windows build.
Changed file extension of the destination of the copy of libomp.lib
(it was mistakely .dll, now it is .lib) in installation on Windows.

Differential Revision: https://reviews.llvm.org/D61673


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360595 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-13 16:07:37 +00:00
Alexey Bataev d5bb0a8d36 [OPENMP][NVPTX]Simplify handling of thread limit, NFC.
Summary:
Patch improves performance of the full runtime mode by moving
threads limit counter to the shared memory. It also allows to save
global memory.

Reviewers: grokos, kkwli0, gtbercea

Subscribers: guansong, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61801

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360584 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-13 14:21:46 +00:00
Alexey Bataev d140b83ae9 [OPENMP][NVPTX]Improve number of threads counter, NFC.
Summary:
Patch improves performance of the full runtime mode by moving
number-of-threads counter to the shared memory. It also allows to save
global memory.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jfb, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61785

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360457 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-10 18:56:05 +00:00
Jonathan Peyton e55ab99292 [OpenMP] Workaround gfortran bugzilla build bug 41755
This patch provides workaround to allow gfortran to compile the
OpenMP Fortran modules.

From the gfortran manual:
https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gfortran/BOZ-literal-constants.html

"Note that initializing an INTEGER variable with a statement such as
DATA i/Z'FFFFFFFF'/ will give an integer overflow error rather than the desired
result of -1 when i is a 32-bit integer on a system that supports 64-bit
integers. The -fno-range-check option can be used as a workaround for legacy
code that initializes integers in this manner."

Bug filed: https://bugs.llvm.org/show_bug.cgi?id=41755

Differential Revision: https://reviews.llvm.org/D61603


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360299 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-08 23:12:31 +00:00
Dimitry Andric aebe831622 Add non-SSE wrapper for __kmp_{load,store}_mxcsr
Summary:
To be able to successfully build OpenMP on FreeBSD/i386, which still
uses i486 as its default processor, I had to provide wrappers for the
`__kmp_load_mxcsr` and `__kmp_store_mxcsr` functions.

If the compiler signals that SSE is not available, loading and storing
mxcsr does not make sense anway, so in that case the inline functions
are empty.  This gives the minimum amount of code churn.

See also https://svnweb.freebsd.org/changeset/base/345283

Reviewers: emaste, jlpeyton, Hahnfeld

Reviewed By: jlpeyton

Subscribers: hfinkel, krytarowski, jdoerfert, openmp-commits, llvm-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60916

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@360062 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-06 17:58:03 +00:00
Alexey Bataev ae9830cdb8 [OPENMP][NVPTX]Improve thread limit counter, NFC.
Summary:
Patch improves performance of the full runtime mode by moving
thread-limit counter to the shared memory. It also allows to save
global memory.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jdoerfert, caomhin, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61526

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359922 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-03 20:00:38 +00:00
Alexey Bataev 49325fc6ab [OPENMP][NVPTX]Improved several standard OpenMP functions, NFC.
Summary:
Used parallelLevel[] counter to simplify and improve implementation of
the existing standard OpenMP functions. Functions are tested already in
several tests, the patch is NFC.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jdoerfert, caomhin, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61459

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359892 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-03 14:47:20 +00:00
Alexey Bataev 2d4c5f915a [OPENMP][NVPTX]Improve code by using parallel level counter.
Summary:
Previously for the different purposes we need to get the active/common
parallel level and with full runtime we iterated over all the records to
calculate this level. Instead, we can used the warp-based parallel level
counters used in no-runtime mode.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jfb, jdoerfert, caomhin, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61395

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359822 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-02 20:05:01 +00:00
Alexey Bataev db75b85d57 [OPENMP][NVPTX]Improve omp_get_max_threads() function.
Summary:
Function omp_get_max_threads() can always return 1 if current execution
mode is SPMD.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jdoerfert, caomhin, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61379

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359792 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-02 14:52:52 +00:00
Alexey Bataev 573fae7275 [OPENMP][NVPTX]Improved omp_get_thread_limit() function.
Summary:
Function omp_get_thread_limit() in SPMD mode can return the maximum
available number of threads as a result.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D61378

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359790 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-02 14:46:32 +00:00
Dimitry Andric ca840d66bb Enable OpenMP build for 32-bit FreeBSD
Summary:
To be able to successfully build OpenMP on 32-bit FreeBSD, such as
FreeBSD/i386, I first had to provide a few wrappers (see D60916), and
then add `KMP_OS_FREEBSD` to the list of defines checked for 32-bit
architectures in `kmp_runtime.cpp`.

I have successfully built libomp.so and ran a bunch of test programs on
FreeBSD/i386 with this.

See also https://svnweb.freebsd.org/changeset/base/345283

Reviewers: emaste, jlpeyton, Hahnfeld

Reviewed By: jlpeyton

Subscribers: krytarowski, guansong, jdoerfert, openmp-commits, llvm-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60917

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359716 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-01 19:32:58 +00:00
Jonathan Peyton 9377fa9653 [OpenMP] Implement task modifier for reduction clause
Implemented task modifier in two versions - one without taking into account
omp_orig variable (the omp_orig still can be processed by compiler without help
of the library, but each reduction object will need separate initializer with
global access to omp_orig), another with omp_orig variable included into
interface (single initializer can be used for multiple reduction objects of
the same type). Second version can be used when the omp_orig is not globally
accessible, or to optimize code in case of multiple reduction objects
of the same type.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D60976


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359710 91177308-0d34-0410-b5e6-96231b3b80d8
2019-05-01 17:54:01 +00:00
Jonathan Peyton 67ef47a8a1 [OpenMP] Add OpenMP 5.0 nonmonotonic code
This patch adds:
* New omp_sched_monotonic flag to omp_sched_t which is handled within the runtime
* Parsing of monotonic/nonmonotonic in OMP_SCHEDULE
* Tests for the monotonic flag and envirable parsing
* Logic to force monotonic when hierarchical scheduling is used

Differential Revision: https://reviews.llvm.org/D60979


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359601 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-30 19:20:35 +00:00
Jonathan Peyton 03f8ac57f0 [OpenMP] Eliminate some compiler warnings
* Remove accidental == for =
* Assign values to variables to appease compiler
* Surround debug code with KMP_DEBUG
* Remove unused local typedefs

Differential Revision: https://reviews.llvm.org/D60983


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359599 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-30 19:13:37 +00:00
Alexey Bataev 867a57389a [OPENMP][NVPTX]Correctly handle L2 parallelism in SPMD mode.
Summary:
The parallelLevel counter must be on per-thread basis to fully support
L2+ parallelism, otherwise we may end up with undefined behavior.
Introduce the parallelLevel on per-warp basis using shared memory. It
allows to avoid the problems with the synchronization and allows fully
support L2+ parallelism in SPMD mode with no runtime.

Reviewers: gtbercea, grokos

Subscribers: guansong, jdoerfert, caomhin, kkwli0, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60918

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@359341 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-26 19:30:34 +00:00
Dimitry Andric 777f60f39b Use correct way to test for MIPS arch after rOMP355687
Summary:
I ran into some issues after rOMP355687, where __atomic_fetch_add was
being used incorrectly on x86, and this turns out to be caused by the
following added conditionals:

```
#if defined(KMP_ARCH_MIPS)
```

The problem is, these macros are always defined, and are either 0 or 1
depending on the architecture.  E.g. the correct way to test for MIPS
is:

```
#if KMP_ARCH_MIPS
```

Reviewers: petarj, jlpeyton, Hahnfeld, AndreyChurbanov

Reviewed By: petarj, AndreyChurbanov

Subscribers: AndreyChurbanov, sdardis, arichardson, atanasyan, jfb, jdoerfert, openmp-commits, llvm-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60938

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@358911 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-22 19:20:46 +00:00
Alexey Bataev a76db752a7 [OPENMP][NVPTX] Fix the test, NFC.
Fix the test to run it really in SPMD mode without runtime. Previously
it was run in SPMD + full runtime mode and does not allow to cehck the
functionality correctly.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@358902 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-22 17:25:31 +00:00
Andrey Churbanov 31b09e96f2 Fixed memory leak reported in Bugzilla:
https://bugs.llvm.org/show_bug.cgi?id=41494

Freed th_cg_roots structure at exit from uber thread.

Differential Revision: https://reviews.llvm.org/D60729


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@358572 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-17 10:44:28 +00:00
Alexey Bataev 6c198765a0 [OPENMP][NVPTX]Fix dynamic scheduling in L2+ SPMD parallel regions.
Summary:
If the kernel is executed in SPMD mode and the L2+ parallel for region
with the dynamic scheduling is executed, dynamic scheduling functions
are called. They expect full runtime support, but SPMD kernels may be
executed without the full runtime. It leads to the runtime crash of the
compiled program. Patch fixes this problem + fixes handling of the
parallelism level in SPMD mode, which is required as part of this patch.

Reviewers: gtbercea, kkwli0, grokos

Subscribers: guansong, jdoerfert, openmp-commits, caomhin

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D60578

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@358442 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-15 20:15:20 +00:00
Jonathan Peyton c1629ee231 [OpenMP] Exchange code in asm file for inline assembly
This change replaces some of the assembly functions in z_Linux_asm.S
for inline asm in kmp.h. This allows better interaction with compiler
tools and sanitizers.

Differential Revision: https://reviews.llvm.org/D60423


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@358438 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-15 19:19:57 +00:00
Andrey Churbanov cc33e97870 Fixed possible out of bound array access.
The check of index value moved to before the write to the array.

Differential Revision: https://reviews.llvm.org/D60471


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@358181 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-11 15:03:44 +00:00
Jonathan Peyton e45eef02bb [OpenMP] Implement 5.0 memory management
* Replace HBWMALLOC API with more general MEMKIND API, new functions
  and variables added.
* Have libmemkind.so loaded when accessible.
* Redirect memspaces to default one except for high bandwidth which
  is processed separately.
* Ignore some allocator traits e.g., sync_hint, access, pinned, while
  others are processed normally e.g., alignment, pool_size, fallback,
  fb_data, partition.
* Add tests for memory management

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D59783


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@357929 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-08 17:59:28 +00:00
Jonathan Peyton 258655da08 [OpenMP] Clean up load balancing dynamic mode
This patch cleans up the bookkeeping code for the load balancing dynamic mode.

When a thread is moved to or from the thread pool, the th_active_in_pool flag
and the __kmp_thread_pool_active_nth global counter are both updated. This
removes the need for the corrective code in the main wait loop. Another global
counter, __kmp_thread_pool_nth, was removed completely, as it was only used for
debugging, but was not under KMP_DEBUG.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D59508


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@357927 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-08 17:50:02 +00:00
Dimitry Andric 4403c91b6b After rL357618, quote ${CMAKE_THREAD_LIBS_INIT} so CMake does not
complain when the variable is empty.  Fixes PR 41401.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@357828 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-05 22:19:40 +00:00
Jonathan Peyton c8db463d1f [OpenMP] Fix hang on Windows
Debug dump on large machine shows when many OpenMP threads (401 in total)
sleep on a barrier, one of the innermost nesting levels sleeps
on a child's b_arrived flag whose value is equal to 4 and is equal to
checker value. i.e., (1) sleep bit is 0, and (2) done_check() would
return true if called.

It is unclear how this might happen. It could be Windows Server 2016's
error of EnterCriticalSection / LeaveCriticalSection, or
error of WaitForSingleObject / SetEvent / ResetEvent, or
error in the library which is very difficult to find.

As a workaround, change INFINITE wait to timed wait, so that each
thread awakens each 5 seconds (the timeout was chosen arbitrary to not
disturb other threads much), check flag condition under the lock, and
either go to sleep again or stop sleeping as a result of the check.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D59793


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@357722 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-04 20:35:29 +00:00
Jonathan Peyton 3d280aa419 [OpenMP][Stats] Fix stats gathering for distribute and team clause
The distribute clause needs an explicit push of a timer. The teams
clause needs a timer added and also, similarly to parallel, exchanged
with the serial timer when encountered so that serial regions are
counted properly.

Differential Revision: https://reviews.llvm.org/D59801


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@357621 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-03 18:53:26 +00:00
Dimitry Andric cf0276b9ab Ensure correct pthread flags and libraries are used
On most platforms, certain compiler and linker flags have to be passed
when using pthreads, otherwise linking against libomp.so might fail with
undefined references to several pthread functions.

Use CMake's `find_package(Threads)` to determine these for standalone
builds, or take them (and optionally modify them) from the top-level
LLVM cmake files.

Also, On FreeBSD, ensure that libomp.so is linked against libm.so,
similar to NetBSD.

Adjust test cases with hardcoded `-lpthread` flag to use the common
build flags, which should now have the required pthread flags.

Reviewers: emaste, jlpeyton, krytarowski, mgorny, protze.joachim, Hahnfeld

Reviewed By: Hahnfeld

Subscribers: AndreyChurbanov, tra, EricWF, Hahnfeld, jfb, jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D59451


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@357618 91177308-0d34-0410-b5e6-96231b3b80d8
2019-04-03 18:11:36 +00:00
Michael Kruse 3e3199a800 [libomptarget] Introduce LIBOMPTARGET_ENABLE_DEBUG cmake option.
At the moment, support for runtime debug output using the
OMPTARGET_DEBUG=1 environment variable is only available with
CMAKE_BUILD_TYPE=Debug builds. The patch allows setting it independently
using the LIBOMPTARGET_ENABLE_DEBUG option, which is enabled by default
depending on CMAKE_BUILD_TYPE. That is, unless this option is set
explicitly, nothing changes. This is the same mechanism used by LLVM for
LLVM_ENABLE_ASSERTIONS.

This patch also removes adding -g -O0 in debug builds, it should be
handled by cmake's CMAKE_{C|CXX}_FLAGS_DEBUG configuration option.

Idea by Hal Finkel

Differential Revision: https://reviews.llvm.org/D55952

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356998 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-26 15:19:15 +00:00
Jonathan Peyton fe2a27367a [OpenMP] Add LLVM license header to file
This file was missing the LLVM license header



git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356962 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-25 22:36:31 +00:00
Jonathan Peyton e6bc0b3edb [OpenMP] Add Intel 19.0 to list of compilers in kmp_version.cpp
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356961 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-25 22:31:00 +00:00
Dimitry Andric 28e31a2d58 Fix interoperability test compilation on FreeBSD
Summary:
While building the 8.0 releases on FreeBSD, I encountered the following
error in the regression tests, where ompt/misc/interoperability.cpp
failed to compile, with:

```
projects/openmp/runtime/test/ompt/misc/interoperability.cpp:7:10: fatal error: 'alloca.h' file not found
#include <alloca.h>
         ^~~~~~~~~~
```

Like on NetBSD, alloca(3) is defined in <stdlib.h> instead.

Reviewers: emaste, jlpeyton, krytarowski, mgorny, protze.joachim

Reviewed By: jlpeyton

Subscribers: jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D59736

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356936 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-25 18:37:49 +00:00
Dimitry Andric 13cfd61cf5 Fix gettid warnings on FreeBSD
Summary:
[Split off from D59451 to get this fix in separately]

While building the 8.0 releases on FreeBSD, I encountered the following
warnings in openmp quite a few times:

```
In file included from projects/openmp/runtime/src/kmp_settings.cpp:27:
projects/openmp/runtime/src/kmp_wrapper_getpid.h:35:2: warning: #warning is a language extension [-Wpedantic]
#warning No gettid found, use getpid instead
 ^
projects/openmp/runtime/src/kmp_wrapper_getpid.h:35:2: warning: No gettid found, use getpid instead [-W#warnings]
2 warnings generated.
```

I added a gettid wrapper that uses FreeBSD's pthread_getthreadid_np(3)
function for this.

Reviewers: emaste, jlpeyton, krytarowski, mgorny, protze.joachim

Reviewed By: jlpeyton

Subscribers: jfb, jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D59735

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356934 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-25 18:37:14 +00:00
Jonathan Peyton 5696c2b695 [OpenMP] Fix pause check with version info
Add 5.0 guard to pause code for now.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D59428


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356933 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-25 18:17:55 +00:00
Jonathan Peyton 59e2a5754d [OpenMP] Fix OMPT cancellation test for GOMP
The GOMP sections interface uses schedule(dynamic) dispatch so it cannot
be assumed which thread executes the cancel and which thread executes
the cancellation point.  This patch allows either thread to execute either
section.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356302 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-15 21:24:45 +00:00
Jonathan Peyton 9b5ef0220a [OpenMP] Add missing parenthesis in Perl module
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356289 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-15 18:27:14 +00:00
Jonathan Peyton e7e8b2803e [OpenMP] Remove deprecated taskq
Remove very old, unused, and deprecated taskq code.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D58989


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@356288 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-15 18:24:59 +00:00
Jonathan Peyton 922ed1345c [OpenMP][stats] Update stats gathering macros
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355739 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-08 21:23:34 +00:00
Petar Jovanovic e0a1fba241 [mips] Use libatomic instead of GCC intrinsics for 64bit
The following GCC intrinsics are not available on MIPS32:

__sync_fetch_and_add_8
__sync_fetch_and_and_8
__sync_fetch_and_or_8
__sync_val_compare_and_swap_8

Replace these with appropriate libatomic implementation.

Patch by Miodrag Dinic.

Differential Revision: https://reviews.llvm.org/D45691


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355687 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-08 10:53:19 +00:00
Shoaib Meenai 6b80cedde4 [build] Rename clang-headers to clang-resource-headers
Summary:
The current install-clang-headers target installs clang's resource
directory headers. This is different from the install-llvm-headers
target, which installs LLVM's API headers. We want to introduce the
corresponding target to clang, and the natural name for that new target
would be install-clang-headers. Rename the existing target to
install-clang-resource-headers to free up the install-clang-headers name
for the new target, following the discussion on cfe-dev [1].

I didn't find any bots on zorg referencing install-clang-headers. I'll
send out another PSA to cfe-dev to accompany this rename.

[1] http://lists.llvm.org/pipermail/cfe-dev/2019-February/061365.html

Reviewers: beanz, phosek, tstellar, rnk, dim, serge-sans-paille

Subscribers: mgorny, javed.absar, jdoerfert, #sanitizers, openmp-commits, lldb-commits, cfe-commits, llvm-commits

Tags: #clang, #sanitizers, #lldb, #openmp, #llvm

Differential Revision: https://reviews.llvm.org/D58791

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355340 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-04 21:19:53 +00:00
Stefan Pintilie 9aa5fc8a74 [OPENMP] Deal with additional store inserted by Clang under -fno-PIC for PowerPC.
Changing the default from -fPIC to -fno-PIC on PowerPC exposed an issue in
OpenMP for PowerPC.
The issue is reported here:
https://bugs.llvm.org/show_bug.cgi?id=40082

This is a fix for that issue.
Also removed the XFAIL from the two tests that were failing under -fno-PIC.

Differential Revision: https://reviews.llvm.org/D56286

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355229 91177308-0d34-0410-b5e6-96231b3b80d8
2019-03-01 21:16:45 +00:00
Jonathan Peyton 2e429f17a6 [OpenMP][OMPT] Distinguish different barrier kinds
This change makes the runtime decide the intended use of each barrier
invocation, for the OMPT synchronization tool callbacks.  The OpenMP 5.0
specification defines four possible barrier kinds -- implicit, explicit,
implementation, and just normal barrier.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D58247


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355140 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-28 20:55:39 +00:00
Jonathan Peyton 8453ca8594 [OpenMP 5.0] Deprecate nest-var and associated features
Nest-var, OMP_NESTED, omp_set_nested()., and omp_get_nested() have been
deprecated in the 5.0 spec. Initial nesting info is now derived from
OMP_MAX_ACTIVE_LEVELS, OMP_NUM_THREADS, and OMP_PROC_BIND.

This patch deprecates the internal ICV that corresponds to nest-var, and
replaces it with the max-active-levels-var ICV to determine nesting. The
change still allows for use of OMP_NESTED (according to 5.0 changes),
omp_get_nested, and omp_set_nested, which have had deprecation messages
added to them. The change allows certain settings of OMP_NUM_THREADS,
OMP_PROC_BIND, and OMP_MAX_ACTIVE_LEVELS to turn on nesting, but
OMP_NESTED=0 will still force nesting to be off.

The runtime now prints informative messages about deprecation of
OMP_NESTED, omp_set_nested(), and omp_get_nested(), when those
environment variables or routines are used. It also prints deprecated
message in output for KMP_SETTINGS and OMP_DISPLAY_ENV for OMP_NESTED.
This patch also fixes OMP_DISPLAY_ENV output for OMP_TARGET_OFFLOAD.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D58408


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355138 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-28 20:47:21 +00:00
Jonathan Peyton bbb6f01707 [OpenMP] Make use of sched_yield optional in runtime
This patch cleans up the yielding code and makes it optional. An
environment variable, KMP_USE_YIELD, was added. Yielding is still
on by default (KMP_USE_YIELD=1), but can be turned off completely
(KMP_USE_YIELD=0), or turned on only when oversubscription is detected
(KMP_USE_YIELD=2). Note that oversubscription cannot always be detected
by the runtime (for example, when the runtime is initialized and the
process forks, oversubscription cannot be detected currently over
multiple instances of the runtime).

Because yielding can be controlled by user now, the library mode
settings (from KMP_LIBRARY) for throughput and turnaround have been
adjusted by altering blocktime, unless that was also explicitly set.

In the original code, there were a number of places where a double yield
might have been done under oversubscription. This version checks
oversubscription and if that's not going to yield, then it does
the spin check.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D58148


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@355120 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-28 19:11:29 +00:00
Jonas Hahnfeld acb2548dde [OpenMP] Fix check-openmp after r354553
Calling add_openmp_testsuite will add the tests to check-openmp unless
EXCLUDE_FROM_ALL is set. This is problematic because the tests for OMPT
will be included twice which doesn't work if the same test is executed
concurrently by multiple threads.

See:
http://lab.llvm.org:8011/builders/openmp-gcc-x86_64-linux-debian/builds/163
http://lab.llvm.org:8011/builders/openmp-clang-x86_64-linux-debian/builds/184

http://lab.llvm.org:8011/builders/openmp-clang-ppc64le-linux-rhel/builds/133
(On PPC some failures are unrelated to r354553, the bot has been red before
and this commit is not expected to fix that. For a proper patch please see
https://reviews.llvm.org/D56286.)

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@354572 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-21 12:00:57 +00:00
Joachim Protze 698a904a22 [OpenMP][OMPT] Fix locking testcases for 32 bit architectures
Fix for the bug reported in:
https://bugs.llvm.org/show_bug.cgi?id=40531

The address is now casted the same way as in the runtime code.

Differential Revision: https://reviews.llvm.org/D58454

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@354553 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-21 08:50:49 +00:00
Gheorghe-Teodor Bercea eaaceb40bb [OpenMP][libomptarget] New reduction scheme for team reductions
Summary:
This patch adds a more sophisticated team reduction scheme to the OpenMP libomptarget-nvptx runtime.

The scheme uses a fixed size global memory buffer whose length can be adjusted via compiler flag:
```
-fopenmp-cuda-teams-reduction-recs-num=1024
```
The global buffer is a structure of arrays (with default size of 1024 each and controlled by the above flag), one array for each reduction variable.

Values in the buffer are processed by the last team to finish executing the body of the target region.

In addition to adding support for the new flag, the compiler also emits special functions used for the reduction of the intermediate reduction values. These changes will be added in a separate compiler patch following this one.




Reviewers: ABataev, caomhin

Reviewed By: ABataev

Subscribers: guansong, jfb, jdoerfert, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D58409

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@354471 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-20 14:55:55 +00:00
Jonathan Peyton ebd6a4561f [OpenMP] Remove XFAIL for cancellation tests using gcc
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@354370 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-19 19:00:29 +00:00
Jonathan Peyton 85df023bba [OpenMP 5.0] Add omp_get_supported_active_levels()
This patch adds the new 5.0 API function omp_get_supported_active_levels().

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D58211


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@354368 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-19 18:51:11 +00:00
Jonathan Peyton 553654650e [OpenMP] Adding GOMP compatible cancellation
Remove fatal error messages from the cancellation API for GOMP
Add __kmp_barrier_gomp_cancel() to implement cancellation of parallel regions.
This new function uses the linear barrier algorithm with a cancellable
nonsleepable wait loop.

Differential Revision: https://reviews.llvm.org/D57969


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@354367 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-19 18:47:57 +00:00
Jonathan Peyton e518cdac15 [OpenMP] Fix broken link to browse sources
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@353858 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-12 17:00:57 +00:00
Jonathan Peyton bde568706e [OpenMP] Remove accidental commit to config-ix.cmake in r353747
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@353748 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-11 21:09:15 +00:00
Jonathan Peyton e85e92b0ff [OpenMP] Fix thread_limits to work properly for teams construct
The thread-limit-var and omp_get_thread_limit API was not perfectly handled for
teams construct. Now, when modified by thread_limit clause, omp_get_thread_limit
reports the correct value. In addition, the value is restored when leaving the
teams construct to what it was in the encountering context.

This is done partly by creating the notion of a Contention Group root (CG root)
that keeps track of the thread at the root of each separate CG, the
thread-limit-var associated with the CG, and associated counter of active
threads within the contention group.

thread-limits are passed from master to worker threads via an entry in the ICV
data structure. When a "contention group switch" occurs, a new CG root record is
made and passed from master to worker. A thread could potentially have several
CG root records if it encounters multiple nested teams constructs (but at the
moment the spec doesn't allow for nested teams, so the most one could have
currently is 2). The master of the teams masters gets the thread-limit clause
value stored to its local ICV structure, and the other teams masters copy it
from the master. The thread-limit is set from that ICV copy and restored to the
ICV copy when entering and leaving the teams construct.

This change also fixes a bug when the top-level teams construct team gets
reused, and OMP_DYNAMIC was true, which can cause the expected size of this team
to be smaller than what was actually allocated. The fix updates the size of the
team after its threads were reserved.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D56804


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@353747 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-11 21:04:23 +00:00
Jonas Hahnfeld 41cad1362d [OMPT] Remove test output from source tree
%s refers to the test file in the source tree. This was accidentally added in
r351197 / 2b46d30 ("[OMPT] Second chunk of final OMPT 5.0 interface updates").

Differential Revision: https://reviews.llvm.org/D58002

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@353715 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-11 16:14:51 +00:00
Taewook Oh 87a0e3609f Guard a feature that unsupported by old GCC
Summary:
As @david2050 commented, changes introduced by https://reviews.llvm.org/D56397 break builds for older compilers
which don't support `__has(_cpp)_attribute`. This is a fix for the break.

Reviewers: protze.joachim, jlpeyton, AndreyChurbanov, Hahnfeld, david2050

Subscribers: openmp-commits, david2050

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D57851

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@353538 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-08 17:15:50 +00:00
Joachim Protze 9d191f041c [OMPT] Make sure that OMPT is enabled when accessing internals of the runtime
The three switch fallthrough generate a warning with -Wimplicit-fallthrough.
Two are documented as fallthrough, one is not, but I think the intention is to also fallthrough in kmp_tasking.cpp.

Not sure whether kmp.h is the best place to define the macro.

Reviewers: jlpeyton, AndreyChurbanov, Hahnfeld

Reviewed By: jlpeyton

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D56397

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@353052 91177308-0d34-0410-b5e6-96231b3b80d8
2019-02-04 15:59:42 +00:00
Joachim Protze 71c5f3cb2f [OMPT] Make sure that OMPT is enabled when accessing internals of the runtime
Redo after revert by hans. The wrong include in one test is fixed.

Make sure that OMPT is enabled in runtime entry points that access internals
of the runtime. Else, return an appropiate value indicating an error or that
the data is not available.

Patch provided by @sconvent

Reviewers: jlpeyton, omalyshe, hbae, Hahnfeld, joachim.protze

Reviewed By: joachim.protze

Tags: #openmp, #ompt

Differential Revision: https://reviews.llvm.org/D47717

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@352611 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-30 08:41:06 +00:00
James Y Knight 2853609484 Adjust documentation for git migration.
This fixes most references to the paths:
 llvm.org/svn/
 llvm.org/git/
 llvm.org/viewvc/
 github.com/llvm-mirror/
 github.com/llvm-project/
 reviews.llvm.org/diffusion/

to instead point to https://github.com/llvm/llvm-project.

This is *not* a trivial substitution, because additionally, all the
checkout instructions had to be migrated to instruct users on how to
use the monorepo layout, setting LLVM_ENABLE_PROJECTS instead of
checking out various projects into various subdirectories.

I've attempted to not change any scripts here, only documentation. The
scripts will have to be addressed separately.

Additionally, I've deleted one document which appeared to be outdated
and unneeded:
  lldb/docs/building-with-debug-llvm.txt

Differential Revision: https://reviews.llvm.org/D57330

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@352514 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-29 16:37:27 +00:00
Arnaud A. de Grandmaison 95c11ec5a9 Remove no longer needed Arm specific words in the LICENSE.txt file.
As the codebase is now under the Apache 2.0 license with LLVM
Exceptions, and all Arm's contributions, past or future, are under that
new license, this Arm specific words in LICENSE.txt are no longer
needed.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@352377 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-28 15:42:58 +00:00
Andrey Churbanov c1fe93aaa4 NFC: fixed formatting to be consistent across the file
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351748 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-21 16:11:43 +00:00
Andrey Churbanov f30a96a18f Fixed https://reviews.llvm.org/D55078 broken Fortran fixed form.
Long lines split in order to obey Fortran fixed form compilation.

Differential Revision: https://reviews.llvm.org/D57017


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351745 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-21 15:30:31 +00:00
Chandler Carruth 4b75f4e92a Fix typos throughout the license files that somehow I and my reviewers
all missed!

Thanks to Alex Bradbury for pointing this out, and the fact that I never
added the intended `legacy` anchor to the developer policy. Add that
anchor too. With hope, this will cause the links to all resolve
successfully.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351731 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-21 09:52:34 +00:00
Chandler Carruth 7e084d9fdf Update more file headers across all of the LLVM projects in the monorepo
to reflect the new license. These used slightly different spellings that
defeated my regular expressions.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351648 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-19 10:56:40 +00:00
Chandler Carruth 42bf584150 Install new LLVM license structure and new developer policy.
This installs the new developer policy and moves all of the license
files across all LLVM projects in the monorepo to the new license
structure. The remaining projects will be moved independently.

Note that I've left odd formatting and other idiosyncracies of the
legacy license structure text alone to make the diff easier to read.
Critically, note that we do not in any case *remove* the old license
notice or terms, as that remains necessary until we finish the
relicensing process.

I've updated a few license files that refer to the LLVM license to
instead simply refer generically to whatever license the LLVM project is
under, basically trying to minimize confusion.

This is really the culmination of so many people. Chris led the
community discussions, drafted the policy update and organized the
multi-year string of meeting between lawyers across the community to
figure out the strategy. Numerous lawyers at companies in the community
spent their time figuring out initial answers, and then the Foundation's
lawyer Heather Meeker has done *so* much to help refine and get us ready
here. I could keep going on, but I just want to make sure everyone
realizes what a huge community effort this has been from the begining.

Differential Revision: https://reviews.llvm.org/D56897

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351631 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-19 06:14:24 +00:00
Hans Wennborg e223da31a4 Revert r351311 "[OMPT] Make sure that OMPT is enabled when accessing internals of the runtime"
and also the follow-up r351315.

The new test is failing on the buildbots.

> Make sure that OMPT is enabled in runtime entry points that access internals
> of the runtime. Else, return an appropiate value indicating an error or that
> the data is not available.
>
> Patch provided by @sconvent
>
> Reviewers: jlpeyton, omalyshe, hbae, Hahnfeld, joachim.protze
>
> Reviewed By: joachim.protze
>
> Tags: #openmp, #ompt
>
> Differential Revision: https://reviews.llvm.org/D47717

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351431 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-17 11:31:03 +00:00
Jonathan Peyton 4338c2574e [OpenMP] Add omp_pause_resource* API
Add omp_pause_resource and omp_pause_resource_all API and enum, plus stub for
internal implementation. Implemented callable helper function to do local pause,
and added basic functionality for hard and soft pause.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D55078


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351372 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-16 20:07:39 +00:00
Joachim Protze da71b1ee45 [OpenMP] Output written by tests should go to build directory
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351332 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-16 13:06:10 +00:00
Joachim Protze 9c08284967 [OpenMP] Remove compiler warning about unused value
The compiler warns about an unused variable/statement:

    runtime/src/kmp_affinity.cpp:4958:18: warning: statement has no effect [-Wunused-value]
       KA_TRACE(1000, ; {
                      ^
    runtime/src/kmp_debug.h:84:24: note: in definition of macro 'KA_TRACE'
         __kmp_debug_printf x;                                                      \
                            ^

Instead of the unused reference to this function, this patch now calls the function
with an empty string. The call to this function should have no effect.

Patch provided by joachim.protze

Reviewers: jlpeyton, hbae, AndreyChurbanov

Reviewed By: AndreyChurbanov

Tags: #openmp, #ompt

Differential Revision: https://reviews.llvm.org/D56775

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351323 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-16 11:35:11 +00:00
Joachim Protze c7550f83fb Fix compiler error in r351311
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351315 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-16 09:39:42 +00:00
Joachim Protze 16228bba2f [OMPT] Make sure that OMPT is enabled when accessing internals of the runtime
Make sure that OMPT is enabled in runtime entry points that access internals
of the runtime. Else, return an appropiate value indicating an error or that
the data is not available.

Patch provided by @sconvent

Reviewers: jlpeyton, omalyshe, hbae, Hahnfeld, joachim.protze

Reviewed By: joachim.protze

Tags: #openmp, #ompt

Differential Revision: https://reviews.llvm.org/D47717

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351311 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-16 08:58:17 +00:00
Jonathan Peyton c43ee4db7e [OpenMP] Fix for nested proc_bind affinity bug
Using proc_bind clause on a nested #pragma omp parallel region
with KMP_AFFINITY set causes an assertion error. This assertion occurs because
the place-partition-var is not properly initialized in the nested master threads.
Trying to get an intuitive result with KMP_AFFINITY + proc_bind is difficult
because of how the KMP_AFFINITY gtid-to-place mapping occurs. This
patch creates an initial place list no matter what affinity mechanism is used.
For KMP_AFFINITY, the place-partition-var is initialized to all the places.

Differential Revision: https://reviews.llvm.org/D55795


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351227 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-15 19:39:32 +00:00
Jonathan Peyton 9a1cb103a1 [OpenMP] Add lock function definitions to fix Bug 40042
This change fixes the sanity issue reported in Bug 40042.
Lock function definitions for the three lock kinds were added
to disambiguate calls to the lock functions done directly and indirectly.

Bugzilla: https://bugs.llvm.org/show_bug.cgi?id=40042
Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D56103


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351224 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-15 19:14:00 +00:00
Jonathan Peyton 4cb0b6cbbc [OpenMP][Cmake] Allowed OpenMP testing detect test compiler with same generator
Fix ninja build detect test compiler failed under windows.

Patch by Peiyuan Song

Differential Revision: https://reviews.llvm.org/D53479


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351223 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-15 19:08:26 +00:00
Jonathan Peyton eb95f61acb [OpenMP] Fix performance regression in SPEC kdtree test
Make __ompt_implicit_task_end a static function and remove the inline part.  Remove
pId variable that is unused.  This fixes small regression in SPEC kdtree benchmark.
Also reformat some of __ompt_implicit_task_end.

Differential Revision: https://reviews.llvm.org/D55788


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351221 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-15 18:57:24 +00:00
Joachim Protze f52d8ccc95 [OMPT] Second chunk of final OMPT 5.0 interface updates
The omp-tools.h file is generated from the OpenMP spec to ensure that the interface
is implemented as specified.
The other changes are necessary to update the interface implementation to the
final version as published in 5.0.
The omp-tools.h header was previously called ompt.h, currently a copy under this name
is installed for legacy tools.

Patch partially perpared by @sconvent

Reviewers: AndreyChurbanov, hbae, Hahnfeld

Reviewed By: hbae

Tags: #openmp, #ompt

Differential Revision: https://reviews.llvm.org/D55579

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351197 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-15 15:36:53 +00:00
Hans Wennborg 58ea7bd7b9 Update year in license files
In last year's update (D48219) it was suggested that the release manager
might want to do this, so here we go.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351194 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-15 15:10:32 +00:00
Roman Lebedev 2355503bd2 [OpenMP] Fix LIBOMP_USE_DEBUGGER=ON build (PR38612)
Summary:
Two things:
1. Those two variables had the wrong sigdness, which was resulting in "sign mismatch in comparison" warning.
2. The whole `kmp_debugger.cpp` wasn't being built, or rather, it was being built as-if `USE_DEBUGGER` was off,
   thus, nothing provided the definition of `__kmp_omp_debug_struct_info`, `__kmp_debugging`.
   Makes sense, because `USE_DEBUGGER` is set in `kmp_config.h`, which is not included explicitly.
   It is included by `kmp.h`, but that one is only included inside of the `#if USE_DEBUGGER` block..
   I *think* this is the only source file with this issue,
   everything else seem to `#include` either `kmp.h` or `kmp_config.h`.
   The alternative solution would be to add `add_compile_options(-include kmp_config.h)` in CMake.

I did verify that `__kmp_omp_debug_struct_info` becomes available with this patch.

Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=38612 | PR38612 ]].

Reviewers: AndreyChurbanov, jlpeyton, Hahnfeld

Reviewed By: jlpeyton

Subscribers: guansong, jfb, openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D55783

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351019 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-13 12:54:34 +00:00
Gheorghe-Teodor Bercea abb31f1d1f [OpenMP][libomptarget] Use shared memory variable for tracking parallel level
Summary: Replace existing infrastructure for tracking parallel level using global memory with a per-team shared memory variable. This minimizes the impact of the overhead of tracking the parallel level for non-nested cases.

Reviewers: ABataev, caomhin

Reviewed By: ABataev

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D55773

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350747 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-09 18:30:14 +00:00
Andrey Churbanov 766c19dcb0 Doc: fixed description of a parameter of the __kmpc_taskloop
Patch by sergi.mateo.bellido@gmail.com

Differential Revision: https://reviews.llvm.org/D56432


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350713 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-09 13:06:23 +00:00
Alexey Bataev 12eef27677 [OPENMP][NVPTX]Fix dynamic scheduling.
Summary:
Previous implementation may cause the runtime crash when the number of
teams is > 1024. Patch fixes this problem + reduces number of the atomic
operations by 32 times.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jfb, openmp-commits, caomhin

Differential Revision: https://reviews.llvm.org/D56332

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350524 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-07 14:25:25 +00:00
Alexey Bataev 38895e681e [OPENMP][NVPTX]General formatting/code improvement, NFC.
Summary: Formatting.

Reviewers: gtbercea, grokos, kkwli0

Subscribers: guansong, openmp-commits, caomhin

Differential Revision: https://reviews.llvm.org/D56290

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350431 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-04 20:16:54 +00:00
Alexey Bataev 900210a375 [OPENMP][NVPTX]Improve performance + reduce number of used registers.
Summary:
Reduced number of the used register + improved performance propagating
the information about current execution/data sharing mode directly from
the compiler, where it is possible.
In some cases, it requires new/reworked interfaces of the runtime
external functions. Old functions are marked as deprecated.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, jfb, openmp-commits, caomhin

Differential Revision: https://reviews.llvm.org/D56278

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350405 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-04 17:09:12 +00:00
Joel E. Denny 58df0162f1 [OpenMP] Fix nvidia-cuda-toolkit detection on Debian/Ubuntu
The OpenMP runtime's cmake scripts do not correctly locate the
libdevice that the Debian/Ubuntu package nvidia-cuda-toolkit currently
includes, at least on my Ubuntu 18.04.1 installation.  This patch
fixes that for me.

This problem was discussed at length in D55269.  D40453 added a
similar adjustment in clang, but reviewers of D55269 concluded that,
for the OpenMP runtime, the right place to address this problem is in
cmake's CUDA support.  However, it was also suggested we could add a
workaround to OpenMP's cmake scripts now.  This patch contains such a
workaround, which I've tried to design so that it will have no harmful
effect if cmake improves in the future.

nvidia-cuda-toolkit also needs improvements because its intended
monolithic CUDA tree shim, /usr/lib/cuda, has many empty directories,
such as bin.  I reported that at:

<https://bugs.launchpad.net/ubuntu/+source/nvidia-cuda-toolkit/+bug/1808999>

Reviewed By: grokos

Differential Revision: https://reviews.llvm.org/D55588

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350377 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-04 02:07:13 +00:00
Jonathan Peyton a999c520ac [OpenMP] Add omp_get_device_num() and update several other device API functions
Add omp_get_device_num() function for 5.0 which returns the number of the
device the current thread is running on. Currently, we are leaving it to the
compiler to handle this properly if it is called inside target.

Also, did some cleanup and updating of duplicate device API functions (in both
libomp and libomptarget) to make them into weak functions that check for the
symbol from libomptarget, and will call the version in libomptarget if it is
present. If any additional device API functions are implemented also in
libomptarget in the future, we should add the dlsym calls to the host functions.
Also, if the omp_target_* functions are to be implemented for the host (this has
been requested), they should attempt to call the libomptarget versions as well.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D55578


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350352 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-03 21:14:19 +00:00
Alexey Bataev c0c737ac56 [OPENMP][NVPTX]Fix incompatibility of __syncthreads with LLVM, NFC.
Summary:
One of the LLVM optimizations, split critical edges, also clones tail
instructions. This is a dangerous operation for __syncthreads()
functions and this transformation leads to undefined behavior or
incorrect results. Patch fixes this problem by replacing __syncthreads()
function with the assembler instruction, which cost is too high and
wich cannot be copied.

Reviewers: grokos, gtbercea, kkwli0

Subscribers: guansong, openmp-commits, caomhin

Differential Revision: https://reviews.llvm.org/D56274

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350333 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-03 17:43:46 +00:00
Vyacheslav Zakharin 270adfa61a [libomptarget] Added install component for libomptarget
Differential Revision: https://reviews.llvm.org/D56108


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350254 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-02 19:39:49 +00:00
Alexey Bataev a04cc5ff8b [OPENMP][NVPTX]Added/fixed debugging messages, NFC.
Summary: Added or fixed new/old debugging messages for the better diagnostics.

Reviewers: gtbercea, kkwli0, grokos

Reviewed By: grokos

Subscribers: caomhin, guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D56102

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350137 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-28 21:36:09 +00:00
Alexey Bataev 6f4c90a4f5 [OPENMP][NVPTX]Fixed initialization of the data-sharing interface.
Summary:
Avoid using of the atomic loop to wait for the completion of the
data-sharing interface initialization, use __shfl_sync instead for the
communication within the warp to signal other threads in the warp about
completion of the initialization.

Reviewers: gtbercea, kkwli0, grokos

Subscribers: guansong, jfb, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D56100

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350129 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-28 17:31:06 +00:00
Alexey Bataev b4efbcf3fe [OPENMP][NVPTX]Outline assert into noinline function, NFC.
Summary:
At high optimization level asserts lead to some unexpected results
because of auto-inserted unreachable instructions. This outlining
prevents some of such dangerous optimizations and leads to better
stability.

Reviewers: gtbercea, kkwli0, grokos

Subscribers: guansong, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D56101

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350128 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-28 17:29:47 +00:00
Michal Gorny 1f1c3ec263 [runtime] [test] Fix using %python path
Fix the newly-added tests to use %python substitution in order to use
the correct path to Python interpreter.  Otherwise, they fail on NetBSD
where there is no 'python', just 'pythonX.Y'.

Differential Revision: https://reviews.llvm.org/D56048

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@350001 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-22 10:51:53 +00:00
Stefan Pintilie 7a5b7589b9 [Tests] [OpenMP] XFAIL also for ppc64le.
Two tests were XFAILed for powerpc64le in r349512.
They should have also been XFAILed for ppc64le.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349521 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-18 19:05:07 +00:00
Stefan Pintilie 4918c86552 XFAIL Pair of OpenMP Tests for PowerPC LE Linux
XFAIL two tests that fail on PowerPC LE Linux due
to the change of default from PIC to no-PIC on that
platform.

A Bug has been opened for this:
https://bugs.llvm.org/show_bug.cgi?id=40082

The tests are:
runtime/test/ompt/misc/control_tool.c
runtime/test/ompt/synchronization/taskwait.c

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349512 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-18 17:39:22 +00:00
Joachim Protze 880387ae38 [Tests] fix non-determinism failure in testcase
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349460 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-18 08:57:23 +00:00
Joachim Protze daa386bb15 [OMPT] First chunk of final OMPT 5.0 interface updates
This patch updates the implementation of the ompt_frame_t, ompt_wait_id_t
and ompt_state_t. The final version of the OpenMP 5.0 spec added the "t"
for these types.
Furthermore the structure for ompt_frame_t changed and allows to specify
that the reenter frame belongs to the runtime.

Patch partially prepared by Simon Convent

Reviewers: hbae

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349458 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-18 08:52:30 +00:00
Joachim Protze c89e1255ba [OMPT] Add testcase for thread_num provided by implicit task events
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349457 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-18 08:52:12 +00:00
Jonathan Peyton f9fd93f0a3 [OpenMP] version the affinity format tests and fix one test
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349412 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-17 22:53:47 +00:00
Jonathan Peyton 91e1c35cfa [OpenMP] Add affinity format tests
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349411 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-17 22:33:21 +00:00
Roman Lebedev 600918d9e3 [OpenMP] Fixes for LIBOMP_OMP_VERSION=45/40
Summary:
I have discovered this because i wanted to experiment with
building static libomp (with openmp-4.0 support only)
for debugging purposes.

There are three kinds of problems here:
1. `__kmp_compare_and_store_acq()` simply does not exist.
   It was added in D47903 by @jlpeyton.
   I'm guessing `__kmp_atomic_compare_store_acq()` was meant.
2. In `__kmp_is_ticket_lock_initialized()`,
   `lck->lk.initialized` is `std::atomic<bool>`,
   while `lck` is `kmp_ticket_lock_t *`.
   Naturally, they can't be equality-compared.
   Either, it should return the value read from `lck->lk.initialized`,
   or do what `__kmp_is_queuing_lock_initialized()` does,
   compare the passed pointer with the field in the struct
   pointed by the pointer. I think the latter is correct-er choice here.
3. Tests were not versioned.
   They assume that `LIBOMP_OMP_VERSION` is at the latest version.

This does not touch LIBOMP_OMP_VERSION=30. That is still broken.

Reviewers: jlpeyton, Hahnfeld, AndreyChurbanov

Reviewed By: AndreyChurbanov

Subscribers: guansong, jfb, openmp-commits, jlpeyton

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D55496

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349260 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-15 09:23:39 +00:00
Jonathan Peyton 7635714732 [OpenMP] Fix transient divide by zero bug in 32-bit code
The value returned by __kmp_now_nsec() can overflow 32-bit values causing
incorrect values to be returned. The overflow can end up causing a divide
by zero error because in __kmp_initialize_system_tick(), the value
(__kmp_now_nsec() - nsec) can end up being much larger than the numerator:
1e6 * (delay + (now - goal))
during a pathological timing where the current time calculated is much larger
than nsec. When this happens, the value of __kmp_ticks_per_msec is set to zero
which is then used as the denominator in the KMP_NOW_MSEC() macro leading to
the divide by zero error.

Differential Revision: https://reviews.llvm.org/D55300


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349090 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-13 23:18:55 +00:00
Jonathan Peyton 0918584865 [OpenMP] Implement OpenMP 5.0 affinity format functionality
This patch adds the affinity format functionality introduced in OpenMP 5.0.
This patch adds: Two new environment variables:

OMP_DISPLAY_AFFINITY=TRUE|FALSE
OMP_AFFINITY_FORMAT=<string>
and Four new API:
1) omp_set_affinity_format()
2) omp_get_affinity_format()
3) omp_display_affinity()
4) omp_capture_affinity()
The affinity format functionality has two ICV's associated with it:
affinity-display-var (bool) and affinity-format-var (string).
The affinity-display-var enables/disables the functionality through the
envirable OMP_DISPLAY_AFFINITY. The affinity-format-var is a formatted
string with the special field types beginning with a '%' character
similar to printf
For example, the affinity-format-var could be:
"OMP: host:%H pid:%P OStid:%i num_threads:%N thread_num:%n affinity:{%A}"

The affinity-format-var is displayed by every thread implicitly at the beginning
of a parallel region when any thread's affinity has changed (including a brand
new thread being spawned), or explicitly using the omp_display_affinity() API.
The omp_capture_affinity() function can capture the affinity-format-var in a
char buffer. And omp_set|get_affinity_format() allow the user to set|get the
affinity-format-var explicitly at runtime. omp_capture_affinity() and
omp_get_affinity_format() both return the number of characters needed to hold
the entire string it tried to make (not including NULL character). If not
enough buffer space is available,
both these functions truncate their output.

Differential Revision: https://reviews.llvm.org/D55148


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349089 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-13 23:14:24 +00:00
Andrey Churbanov 12258aa8d9 Fix for bugzilla https://bugs.llvm.org/show_bug.cgi?id=39970
Broken tests fixed

Differential Revision: https://reviews.llvm.org/D55598


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@349017 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-13 10:04:10 +00:00
Michal Gorny 3a4f262765 [runtime] Disable KMP_HAVE_QUAD on NetBSD gcc
Disable KMP_HAVE_QUAD when building via gcc on NetBSD system,
as the build fails due to unimplemented builtins:

  .../kmp_atomic.cpp.o: In function `__kmpc_atomic_cmplx16_mul':
  .../kmp_atomic.cpp:1332: undefined reference to `__multc3'
  .../kmp_atomic.cpp.o: In function `__kmpc_atomic_cmplx16_div':
  .../kmp_atomic.cpp:1334: undefined reference to `__divtc3'
  ...

Differential Revision: https://reviews.llvm.org/D55478

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348886 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 19:02:14 +00:00
Michal Gorny ee8460486f [runtime] Use getloadavg() on NetBSD as well
Switch NetBSD from reading /proc (which is broken) to getloadavg()
(which is already used by Darwin).  NetBSD discourages using procfs
in favor of system API calls.

Differential Revision: https://reviews.llvm.org/D55486

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348885 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 19:02:09 +00:00
Kamil Rytarowski 67d037d373 Implement __kmp_is_address_mapped() for NetBSD
Summary:
Use the sysctl(3) function to check whether an address is mapped
into the address space.

Reviewers: mgorny, joerg, #openmp

Reviewed By: mgorny

Subscribers: openmp-commits

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D55549

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348874 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 18:35:07 +00:00
Kamil Rytarowski 97619771cf Implement __kmp_gettid() for NetBSD
Summary: _lwp_self() returns current Thread Id in a numeric version on NetBSD.

Reviewers: joerg, mgorny, #openmp

Reviewed By: mgorny

Subscribers: llvm-commits, openmp-commits, #openmp

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D55497

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348873 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 18:34:33 +00:00
Michal Gorny 741abf8b86 [test] [runtime] Permit omp_get_wtick() to return 0.01
Increase the range for omp_get_wtick() test to allow for 0.01
(from <0.01).  This is needed for NetBSD where it returns exactly that
value due to CLOCKS_PER_SEC being 100.  This should not cause
a significant difference from e.g. FreeBSD where it is 128,
and especially from Linux where CLOCKS_PER_SEC is apparently meaningless
and sysconf(_SC_CLK_TCK) gives 100 as well.

Differential Revision: https://reviews.llvm.org/D55493

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348857 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 15:39:34 +00:00
Michal Gorny 84d57ed8c5 [test] [runtime] Do not include alloca.h on NetBSD
On NetBSD, alloca() is in stdlib.h and there is no alloca.h.  Adjust
the includes appopriately.

Differential Revision: https://reviews.llvm.org/D55487

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348856 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 15:39:30 +00:00
Michal Gorny 4bccfc4806 [runtime] [test] Use more portable short options to sort(1)
Pass `-n -s` instead of `--numeric --stable` to sort(1), as long options
are not supported by NetBSD sort implementation.  `-n` is defined
by POSIX, so it should be fully portable.  `-s` is used consistently
at least in GNU sort and FreeBSD sort, and I honestly doubt it would
cause issues with any other implementation supporting `--stable`.

Differential Revision: https://reviews.llvm.org/D55479

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348855 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 15:39:26 +00:00
Michal Gorny 3ccd20f0f6 [cmake] Use -std=gnu++11 to fix alloca() on NetBSD
Prefer using '-std=gnu++11' over '-std=c++11' when available, as NetBSD
exposes the correct alloca() implementation only with gnu* C/C++
standards.

Differential Revision: https://reviews.llvm.org/D55477

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348854 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-11 15:39:22 +00:00
Jonathan Peyton 92f5818ca0 [OpenMP] Fix a few build issues
Fix two build issues:

1) Recent commit 348756 accidentally included Unix clang compilers
   to use immintrin.h when only clang-cl should be using it leading
   to the following error:

openmp-llvm/runtime/src/kmp_lock.cpp:2035:25: error: always_
inline function '_xbegin' requires target feature 'rtm', but would be inlined into function
      '__kmp_test_adaptive_lock_only' that is compiled without support for 'rtm'
          kmp_uint32 status = _xbegin();
This patch changes the guard to use immintrin.h to only use clang-cl instead of all clang

2) gcc-8 gives a warning about multiline comment in kmp_runtime.cpp:
This patch just changes it to a two line comment
openmp-llvm/runtime/src/kmp_runtime.cpp:7697:8: warning: multi-line comment [-Wcomment]
 #endif // KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD  \


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348783 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-10 18:26:50 +00:00
Alexey Bataev e90d5a5074 [OPENMP][NVPTX]Revert __kmpc_shuffle_int64 to its original form.
Summary:
Use the original shuffle implementation for __kmpc_shuffle_int64 since
default implementation uses the same implementation.

Reviewers: gtbercea

Subscribers: guansong, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D55514

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348772 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-10 16:50:36 +00:00
Alexey Bataev a23f780b1a [OPENMP][NVPTX]Enable fast shuffles on 64bit values only if CUDA >= 9.
Summary:
Shuffle on 64bit data is allowed only for CUDA >= 9.0. Also, fixed the
constant for the mask, need one extra L in the end.

Reviewers: gtbercea, kkwli0

Subscribers: guansong, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D55440

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348758 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-10 14:29:05 +00:00
Andrey Churbanov d0892198a1 Support clang compiling under windows-gnu and windows-msvc
Patch by Peiyuan Song <squallatf@gmail.com>

Differential Revision: https://reviews.llvm.org/D53422


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348756 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-10 13:45:00 +00:00
Kamil Rytarowski a72c79b3a9 Add OpenBSD support to OpenMP
Summary: This patch permits OpenMP to build and work (with both gcc and clang) on OpenBSD. It mostly follows what was done for FreeBSD and NetBSD, except OpenBSD does not have pthread_getattr_np support, so it follows OS X in that one instance.

Reviewers: #openmp, krytarowski

Reviewed By: krytarowski

Subscribers: guansong, jfb, emaste, mgorny, krytarowski, #openmp

Tags: #openmp

Differential Revision: https://reviews.llvm.org/D34280

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348726 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-09 16:46:48 +00:00
Kamil Rytarowski b3d05abc41 Add DragonFlyBSD support to OpenMP
Summary:
Additions mostly follow FreeBSD and NetBSD and are not intrusive.
There is similar patch for OpenBSD: https://reviews.llvm.org/D34280

The -lm was being omitted due to -Wl,--as-needed in cmake rule, similar patch is in freebsd-ports/devel/llvm-devel port.

Simple OpenMP programs compile and work as expected:
$ clang-devel ~/omp_hello.c -fopenmp -I/usr/local/llvm-devel/include
$ LD_LIBRARY_PATH=/usr/local/llvm-devel/lib OMP_NUM_THREADS=100 ./a.out

The assertion in LLVMgold.so when -fopenmp was used together with -flto in 20170524 snapshot is no longer triggered on current svn-trunk and works fine as in llvm-4.0 with our local patches.

Reviewers: #openmp, krytarowski

Reviewed By: krytarowski

Subscribers: dexonsmith, jfb, krytarowski, guansong, gregrodgers, emaste, mgorny, mehdi_amini

Differential Revision: https://reviews.llvm.org/D35129

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348725 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-09 16:40:33 +00:00
Alexey Bataev ad8fb24595 [OPENMP][NVPTX]Save registers for optimized builds with enabled logging.
Summary:
Introduced special noinline function log that allows to save some
registers for optimized builds but with enabled logging. Also, it
increases the stability of the optimized builds with inlined runtime.

Reviewers: gtbercea, kkwli0

Reviewed By: gtbercea

Subscribers: caomhin, guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D55436

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348606 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-07 16:08:29 +00:00
Alexey Bataev 5a8f745ca5 [OPENMP][NVPTX]Correct type casting for printf args + simplified shfl64 function.
Summary:
Explicitly casted printf's args to the required types + simplified
shfl64 function.

Reviewers: gtbercea, kkwli0

Subscribers: guansong, jfb, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D55379

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348521 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-06 19:45:48 +00:00
Alexey Bataev 28c12c9c14 [OPENMP][NVPTX]Fix __kmpc_flush to flush the memory per system, not per block.
Summary:
According to the standard, after memory flushing the changes in the
memory must be visible to all the threads in all teams. Patch fixes
this.

Reviewers: gtbercea, kkwli0

Subscribers: guansong, jfb, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D55370

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348491 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-06 15:27:58 +00:00
Gheorghe-Teodor Bercea 71a315102d [OpenMP][libomptarget] Flush intermediate values during team reduction
Summary: Ensure intermediate values of a team reduction are flushed to memory.

Reviewers: ABataev, caomhin

Reviewed By: ABataev

Subscribers: guansong, jfb, openmp-commits

Differential Revision: https://reviews.llvm.org/D55219

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348148 91177308-0d34-0410-b5e6-96231b3b80d8
2018-12-03 15:21:49 +00:00
Alexey Bataev b0a4d9c9aa [OPENMP][NVPTX]Make runtime compatible with the original runtime.
Summary:
Reworked runtime to make it compatible with the requirements of the
original runtime library. Also, simplified some code to reduce number of
function calls.

Reviewers: gtbercea, kkwli0

Subscribers: guansong, jfb, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D55130

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@348003 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-30 16:52:38 +00:00
Jonathan Peyton 591fa693cc Revert r347799: Add omp_get_device_num() and update other device API
There is a conflict between libomptarget and libomp concerning some of the
standard OpenMP device API which needs further intestigation.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347932 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-29 23:56:14 +00:00
Jonathan Peyton 4bf5fcd9d1 [OpenMP] Add stubs for Task affinity API
This patch adds __kmpc_omp_reg_task_with_affinity to register affinity
information for tasks. For now, the affinity information is not used,
and the function always succeeds. This also adds the kmp_task_affinity_info_t
structure to store the task affinity information.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D55026


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347907 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-29 20:04:29 +00:00
Jonathan Peyton 9982959fbe [OpenMP] Rename ompt_mutex_impl_unknown to ompt_mutex_impl_none
This change renames ompt_mutex_impl_unknown to ompt_mutex_impl_none,
following the name change in the specification.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D54347


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347802 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-28 20:19:53 +00:00
Jonathan Peyton f421676039 [OpenMP] Minor cleanup of debug code
* Fix calculation of string length.
* Remove NULL-check of pointer which has been dereferenced.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D54948


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347801 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-28 20:18:06 +00:00
Jonathan Peyton e80a48c537 [OpenMP] Fixed possible array out of bound access
There is low probability that array th_hot_teams can be
accessed out of bound (when many nested levels are requested
to keep hot teams via KMP_HOT_TEAMS_MAX_LEVEL). The patch
adds the check of index that fixes the problem.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D54950


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347800 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-28 20:15:11 +00:00
Jonathan Peyton 03e17c4ce6 [OpenMP] Add omp_get_device_num() and update several other device API functions
Add omp_get_device_num() function for 5.0 which returns the number of the device
the current thread is running on. Also, did some cleanup and updating of device
API functions to make them into weak functions that should be replaced with
libomptarget functions when libomptarget is present.

Patch by Terry Wilmarth

Differential Revision: https://reviews.llvm.org/D54342


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347799 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-28 20:10:26 +00:00
Gheorghe-Teodor Bercea 2b5d51056d [OpenMP][libomptarget] Add new version of SPMD deinit kernel function with argument
Summary: To enable the compiler to optimize parts of the function that are not needed when runtime can be omitted, a new version of the SPMD deinit kernel function is needed. This function takes the runtime required flag as an argument.

Reviewers: ABataev, kkwli0, caomhin

Reviewed By: ABataev

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D54969

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347714 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-27 21:23:40 +00:00
Alexey Bataev d3bcab99b9 [OPENMP][NVPTX]Basic support for reductions across the teams.
Summary:
Added functions __kmpc_nvptx_teams_reduce_nowait_simple and
__kmpc_nvptx_teams_end_reduce_nowait_simple to implement basic support
for reductions across the teams.

Reviewers: gtbercea, kkwli0

Subscribers: guansong, jfb, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D54967

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347710 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-27 21:06:09 +00:00
Gheorghe-Teodor Bercea 1c39e0dcf6 [OpenMP][libomptarget] Refactor SPMD and runtime requirement checking
Summary: Refactor the checking for SPMD mode and whether the runtime is initialized or not. This uses constant flags which enables the runtime to optimize out unused sections of code that depend on these flags.

Reviewers: ABataev, caomhin

Reviewed By: ABataev

Subscribers: guansong, jfb, openmp-commits

Differential Revision: https://reviews.llvm.org/D54960

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347698 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-27 19:45:10 +00:00
Alexey Bataev 3de4398f5b [OPENMP][NVPTX]Improved lock/critical constructs.
Summary: Improved support for critical constructs + omp_..._lock... constructs.

Reviewers: gtbercea, kkwli0, caomhin

Subscribers: guansong, jfb, openmp-commits

Differential Revision: https://reviews.llvm.org/D54766

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@347342 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-20 20:19:36 +00:00
Andrey Churbanov 69e4da403e Fix for bugzilla https://bugs.llvm.org/show_bug.cgi?id=39137.
Do not write to internal structure if it keeps same value.

Differential Revision: https://reviews.llvm.org/D54305


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@346862 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-14 13:49:41 +00:00
Alexey Bataev f5927ac8eb [OPENMP]Make lambda mapping follow reqs for PTR_AND_OBJ mapping.
Summary:
The base pointer for the lambda mapping must point to the lambda capture
placement and pointer must point to the captured variable itself. Patch
fixes this problem.

Reviewers: gtbercea

Subscribers: guansong, openmp-commits, kkwli0, caomhin

Differential Revision: https://reviews.llvm.org/D54260

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@346407 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-08 15:47:30 +00:00
Andrey Churbanov 72eb02b9d3 Add Hurd support.
Patch by samuel.thibault@ens-lyon.org

Differential Revision: https://reviews.llvm.org/D54079


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@346310 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-07 12:27:38 +00:00
Andrey Churbanov 4a7ed293d5 Implementation of OpenMP 5.0 mutexinoutset task dependency type.
Differential Revision: https://reviews.llvm.org/D53380


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@346307 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-07 12:19:57 +00:00
Alexey Bataev cbf35099d6 [OPENMP][OFFLOADING]Change the lambda capturing flags.
Summary:
The previously used combination `PTR_AND_OBJ | PRIVATE` could be used
for mapping of some data in Fortran. Changed it to `PTR_AND_OBJ |
  LITERAL`.

Reviewers: gtbercea

Subscribers: guansong, caomhin, openmp-commits

Differential Revision: https://reviews.llvm.org/D54035

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@345981 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-02 15:24:47 +00:00
Alexey Bataev f3f860a2d6 [OPENMP][NVPTX]Fixed/improved support for globalization in team contexts.
Summary:
Current globalization scheme works correctly only for SPMD+lightweight
runtime mode and does not work for full runtime. Patch improves support
for the globalization scheme + reduces global memory consumption in
  lightweight runtime mode.
Patch adds runtime functions to work with the statically allocated
global memory. It allows to improve performance and memory consumption.
This global memory must be allocated by the compiler.

Reviewers: grokos, kkwli0, gtbercea, caomhin

Subscribers: guansong, jfb, openmp-commits

Differential Revision: https://reviews.llvm.org/D53943

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@345976 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-02 14:43:23 +00:00
Gheorghe-Teodor Bercea 35f8cbccc5 [OpenMP][libomptarget] Add runtime function for pushing coalesced global records
Summary: In the case of coalesced global records, we need to push the exact data size passed in. This patch fixes this by outlining the common functionality of the previous push function and by adding a separate entry point for coalesced pushes. The pop function remains unchanged.

Reviewers: ABataev, grokos, caomhin

Reviewed By: ABataev, grokos

Subscribers: jholewinski, cfe-commits, Hahnfeld, guansong, jfb, openmp-commits

Differential Revision: https://reviews.llvm.org/D53141

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@345867 91177308-0d34-0410-b5e6-96231b3b80d8
2018-11-01 18:08:12 +00:00
Alexey Bataev 78cad4d168 [LIBOMPTARGET] Add support for mapping of lambda captures.
Summary:
Added support for correct mapping of variables captured by reference in
lambdas. That kind of mapping may appear only in target-executable
regions and must follow the original lambda or another lambda capture
for the same lambda.
The expected data: base address - the address of the lambda, begin
pointer - pointer to the address of the lambda capture, size - size of
the captured variable.
When OMP_TGT_MAPTYPE_PTR_AND_OBJ mapping type is seen in
target-executable region, the target address of the last processed item
is taken as the address of the original lambda `tgt_lambda_ptr`. Then,
the pointer to capture on the device is calculated like `tgt_lambda_ptr
+ (host_begin_pointer - host_begin_base)` and the target-based address
of the original variable (which host address is
`*(void**)begin_pointer`) is written to that pointer.

Reviewers: kkwli0, gtbercea, grokos

Subscribers: openmp-commits

Differential Revision: https://reviews.llvm.org/D51107

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@345608 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-30 15:42:12 +00:00
Andrey Churbanov 4925467fdb remove duplicate omp_control_tool export to fix windows build
Patch by squallatf@gmail.com

Differential Revision: https://reviews.llvm.org/D53480


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@345255 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-25 11:04:01 +00:00
Jonathan Peyton d81b10f441 [OpenMP] Convert KMP_DYNAMIC_LIB to a 0 or 1 guard everywhere
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343869 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-05 17:59:39 +00:00
Jonathan Peyton 8e7e0d6ec7 [OpenMP] Fix KMP_DYNAMIC_LIB to be dependent on LIBOMP_ENABLE_SHARED
The KMP_DYNAMIC_LIB guard was hard set to 1. This patch has the guard depend
on CMake variable LIBOMP_ENABLE_SHARED.


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343866 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-05 17:47:58 +00:00
Jonathan Peyton e9c3056dbd [OpenMP][OMPT] Fix unsafe initialization of ompt_data_t objects
Initializing an ompt_data_t object using the pointer union member is potentially
unsafe in 32-bit programs.  This change fixes the issue
by using the constant, ompt_data_none.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D52046


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343785 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-04 14:57:04 +00:00
Jonathan Peyton c39393741e [OpenMP] Shutdown library on Windows if possible for better OMPT behavior
On Windows, child workers are terminated by the parent during the normal
program exit process (ExitProcess()) and they are not able to finish generating
their OpenMP events. We can force manual library shut down in __kmpc_end() to
fix this at least for the cases where __kmpc_end() is properly inserted.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D52628


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343619 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-02 19:15:04 +00:00
Jonas Hahnfeld be73d23db2 [libomptarget-nvptx] Enable asserts in bclib
If the user requested LIBOMPTARGET_NVPTX_DEBUG, include asserts in
the bitcode library. Everything else will have very unpleasent
effects because asserts will appear when falling back to the static
library libomptarget-nvptx.a.

Differential Revision: https://reviews.llvm.org/D52701

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343477 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-01 14:16:55 +00:00
Jonas Hahnfeld 789cb443e4 [libomptarget-nvptx] reduction: Determine if runtime uninitialized
Pass in the correct value of isRuntimeUninitialized() which solves
parallel reductions as reported on the mailing list.
For reference: r333285 did the same for loop scheduling.

Differential Revision: https://reviews.llvm.org/D52725

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343476 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-01 14:14:26 +00:00
Andrey Churbanov 81ef7a1088 Fixed workaround made in https://reviews.llvm.org/D51694.
Patch suggested by Kelvin Li: removed optional "kind=" part of kind-selector
for variables with long names and kind names.

Differential Revision: https://reviews.llvm.org/D52712


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343475 91177308-0d34-0410-b5e6-96231b3b80d8
2018-10-01 14:08:50 +00:00
Jonas Hahnfeld e5c7a85edb [libomptarget-nvptx] Align data sharing stack
NVPTX requires addresses of pointer locations to be 8-byte aligned
or there will be an exception during runtime.
This could happen without this patch as shown in the added test:
getId() requires 4 byte of stack and putValueInParallel() uses 16
bytes to store the addresses of the captured variables.

Differential Revision: https://reviews.llvm.org/D52655

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343402 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-30 09:23:21 +00:00
Jonas Hahnfeld 624d29080c [libomptarget-nvptx] Fix ancestor_thread_num and team_size (non-SPMD)
According to OpenMP 4.5, p250:12-14:

    If the requested nest level is outside the range of 0 and the
    nest level of the current thread, as returned by the omp_get_level
    routine, the routine returns -1.

The SPMD code path will need a similar fix.

Differential Revision: https://reviews.llvm.org/D51787

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343401 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-30 09:23:14 +00:00
Jonas Hahnfeld 0a0af171d2 [libomptarget-nvptx] Add tests for nested parallelism
Clang trunk will serialize nested parallel regions. Check that this
is correctly reflected in various API methods.

Differential Revision: https://reviews.llvm.org/D51786

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343382 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-29 16:02:32 +00:00
Jonas Hahnfeld 5741b91970 [libomptarget-nvptx] Ignore calls to dynamic API
There is no support and according to the OpenMP 4.5, p238:7-9:

    For implementations that do not support dynamic adjustment
    of the number of threads this routine has no effect: the
    value of dyn-var remains false.

Add a test that cancellation and nested parallelism aren't
supported either.

Differential Revision: https://reviews.llvm.org/D51785

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343381 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-29 16:02:25 +00:00
Jonas Hahnfeld e85324c770 [libomptarget-nvptx] Fix number of threads in parallel
If there is no num_threads() clause we must consider the
nthreads-var ICV. Its value is set by omp_set_num_threads()
and can be queried using omp_get_max_num_threads().
The rewritten code now closely resembles the algorithm given
in the OpenMP standard.

Differential Revision: https://reviews.llvm.org/D51783

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343380 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-29 16:02:17 +00:00
Alexey Bataev 119df3803b [OPENMP] Add the test to check that the libomptarget does not cause
infinite loop on removing non-mapped pointer-with-object.

Added test to check that libomptarget does not cause infinite loop when
trying to unmap the pointer-with-object data that was not previously
mapped.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343344 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-28 17:13:11 +00:00
Jonas Hahnfeld 08bc82d162 [libomptarget-nvptx] Add testing infrastructure
This patch also introduces testing for libomptarget-nvptx
which has been missing until now. I propose to add tests for
all bugs that are fixed in the future.
The target check-libomptarget-nvptx is not run by default because
 - we can't determine if there is a GPU plugged into the system.
 - it will require the latest Clang compiler. Keeping compatibility
   with older releases would prevent testing newer code generation
   developed in trunk.

Differential Revision: https://reviews.llvm.org/D51687

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343324 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-28 15:05:43 +00:00
Jonathan Peyton 7371e54788 [OpenMP] Add missing __kmpc_critical_with_hint to dllexports
This patch puts the __kmpc_critical_with_hint function in dllexports
and also replaces some OMP_45_ENABLED to OMP_50_ENABLED

Differential Revision: https://reviews.llvm.org/D52380


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343143 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-26 20:47:25 +00:00
Jonathan Peyton 71f9b0e1ed [OpenMP] Fix balanced affinity so thread's private affinity mask is updated
Balanced affinity only updated the thread's affinity with the operating system.
This change also has the thread's private mask reflect that change as well so
that any API that probes the thread's affinity mask will report the correct
mask value.

Differential Revision: https://reviews.llvm.org/D52379


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343142 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-26 20:43:23 +00:00
Jonathan Peyton 56b88ef572 [OpenMP] Update ittnotify sources
This patch updates the ittnotify sources to the latest
corresponding with Intel(R) VTune(TM) Amplifier 2018

Differential Revision: https://reviews.llvm.org/D52378


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343139 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-26 20:30:00 +00:00
Jonathan Peyton 5ada8050d9 [OpenMP] Fix performance issue from 376.kdtree
This change improves the performance of 376.kdtree by giving the compiler an
opportunity to do inlining and other optimizations for the call path,
__kmpc_omp_task_complete_if0()->__kmp_task_finish(), which is one of the hot
paths in the program; some functions in kmp_taskdeps.cpp were moved to the new
header file, kmp_taskdeps.h to achieve this.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D51889


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343138 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-26 20:24:39 +00:00
Jonathan Peyton 37230a1faa [OpenMP][OMPT] A few improvements
This change includes miscellaneous improvements as follows:
1) Added ompt_get_proc_id() implementation for Windows
2) Added parser and print tool for omp-tool-var, just in case it needs
   to be printed (OMP_DISPLAY_ENV)
3) omp_control_tool is exported on Windows

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D50538


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343137 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-26 20:19:44 +00:00
Gheorghe-Teodor Bercea 83a13b92aa [OpenMP][libomptarget] Set the frame pointer then test empty slot condition
Summary: NFC - just fixing a bug: the empty slot test was before the re-setting of the Stack pointer. 

Reviewers: ABataev, caomhin, Hahnfeld

Reviewed By: ABataev

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D52122

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@343006 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-25 18:48:14 +00:00
Gheorghe-Teodor Bercea e1688b470b [OpenMP][libomptarget] Simplify warp master selection for data sharing
Summary:
There is currently no supported situation where the warp master is not the first thread in the warp.

This also avoids the device execution from hanging on Volta GPUs when ballot_sync is called by a number of threads that is less that the size of a warp.


Reviewers: ABataev, caomhin, grokos

Reviewed By: grokos

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D50188

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@342972 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-25 13:23:32 +00:00
Alexey Bataev e5a629ee54 [OPENMP][NVPTX] Add support for lastprivates/reductions handling in SPMD constructs with lightweight runtime.
Summary:
We need the support for per-team shared variables to support codegen for
lastprivates/reductions. Patch adds this support by using shared memory
if the total size of the reductions/lastprivates is <= 128 bytes,
then  pre-allocated buffer in global memory if size is <= 4K bytes,or
uses malloc/free, otherwise.

Reviewers: gtbercea, kkwli0, grokos

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D51875

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@342737 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-21 14:11:41 +00:00
Alexey Bataev 5cab53912c [OPENMP]Increment iterator when the loop is continued.
Summary:
Missed operation of the incrementing iterator when required just to
continue execution.

Reviewers: kkwli0, gtbercea, grokos

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D51937

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341964 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-11 17:16:26 +00:00
Joachim Protze 059ad35b23 [OMPT] Update types according to TR7
Some types and callback signatures have changed from TR6 to TR7.
Major changes (only adding signatures and stubs):
(-remove idle callback) done by D48362
-add reduction and dispatch callback
-add get_task_memory and finalize_tool runtime entry points
-ompt_invoker_t  becomes ompt_parallel_flag_t
-more types of sync_regions

Patch provided by Simon Convent

Reviewers: hbae, protze.joachim

Differential Revision: https://reviews.llvm.org/D50774

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341834 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-10 14:34:54 +00:00
Jonas Hahnfeld 170abc518b [libomptarget-nvptx] Remove last mentions of __kmpc_print_*
Their implementation was removed during review, delete their
prototype declarations.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341748 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-08 12:10:19 +00:00
Jonathan Peyton aebd27b4dc [OpenMP] Update copyright to 2018
Better late than never


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341703 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-07 20:33:35 +00:00
Jonathan Peyton afaf9baa48 [OpenMP] Change hint parameter type for critical to uint32_t
Add atomic hint flags to the enum.
The hint parameter type was changed to uint32_t in __kmpc_critical_with_hint()

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D51235


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341694 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-07 18:46:40 +00:00
Jonathan Peyton 7eaaab9be9 [OpenMP] Synchronization hint constants added to headers
ident flags reserved for atomic hints.
This patch adds omp_sync_hint_t to omp.h and omp_sync_hint_kind to omp_lib.h.
For better maintainability the list of macros for ident flags was replaced with
a enum. The new KMP_IDENT_ATOMIC_HINT_MASK was added to the enum to
support possible future atomic hints.

Also fix omp_lib.h.var to be under 72 chars again after 5.0 OpenMP Memory commit

Patch by Olga Malysheva

Differential Revision: https://reviews.llvm.org/D51233


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341693 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-07 18:45:13 +00:00
Jonathan Peyton d590b1f16e [OpenMP] Initial implementation of OMP 5.0 Memory Management routines
Implemented omp_alloc, omp_free, omp_{set,get}_default_allocator entries,
and OMP_ALLOCATOR environment variable.

Added support for HBW memory on Linux if libmemkind.so library is accessible
(dynamic library only, no support for static libraries).
Only used stable API (hbwmalloc) of the memkind library
though we may consider using experimental API in future.

The ICV def-allocator-var is implemented per implicit task similar to
place-partition-var.  In the absence of a requested allocator, the uses the
default allocator.

Predefined allocators (the only ones currently available) are made similar
for C and Fortran, - pointers (long integers) with values 1 to 8.

Patch by Andrey Churbanov

Differential Revision: https://reviews.llvm.org/D51232


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341687 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-07 18:25:49 +00:00
Andrey Churbanov 0913dc2564 Fix for https://bugs.llvm.org/show_bug.cgi?id=38839:
Changed style of declarations to be less than 72 char each.

Differential Revision: https://reviews.llvm.org/D51694


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341653 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-07 12:22:04 +00:00
Jonas Hahnfeld bf407340fb [libomptarget] Remove two unneeded includes, NFCI.
Follow-up to r340542 and r340767.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341563 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-06 17:00:57 +00:00
Jonas Hahnfeld ada5cfff6b [libomptaret][test] Announce compiler features
This is a follow-up to r341371: The new test for PR38704 doesn't
work with Clang 6.0. It uses an UNSUPPORTED: clang-6, but that
hasn't worked because the compiler features weren't known to lit.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341448 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-05 07:26:00 +00:00
Sergey Dmitriev 56b2913b62 [libomptarget] Remove Devices from RTLInfoTy
This patch removes unused field `Devices` from `RTLInfoTy`.

Differential Revision: https://reviews.llvm.org/D51653


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341399 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-04 20:23:09 +00:00
Jonas Hahnfeld 88f5f2f15c [libomptarget][CUDA] Use cuDeviceGetAttribute, NFCI.
cuDeviceGetProperties has apparently been deprecated since CUDA 5.0.
Nvidia started using annotations only in CUDA 9.2, so nobody noticed
nor cared before.
The new function returns the same values, tested with a P100.

Differential Revision: https://reviews.llvm.org/D51624

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341372 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-04 15:13:28 +00:00
Jonas Hahnfeld 148228909a [libomptarget] PR38704: Fix erase of ShadowPtrMap
erase() invalidates the iterator and returns a new one pointing
to the following element. The code now follows the example at
https://en.cppreference.com/w/cpp/container/map/erase.
(The added testcase crashes without this patch.)

Reported by David Binderman (https://llvm.org/PR38704)!

Differential Revision: https://reviews.llvm.org/D51623

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341371 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-04 15:13:23 +00:00
Jonas Hahnfeld 44cbbcf605 [libomptarget][NVPTX] Drop dead code and data structures, NFCI.
* cg and HasCancel in WorkDescr were never read and can be removed.
 * This eliminates the last use of priv in ThreadPrivateContext.
 * CounterGroup is unused afterwards.
 * Remove duplicate external declares in omptarget-nvptx.cu that are
   already in the header omptarget-nvptx.h.

Differential Revision: https://reviews.llvm.org/D51622

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341370 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-04 15:13:17 +00:00
Jonas Hahnfeld f45f0fd74f [libomptarget][NVPTX] Fix __kmpc_spmd_kernel_deinit
If the runtime is uninitialized the master thread must Enqueue the
state object, and ALL threads must return immediately.
Found post-commit of https://reviews.llvm.org/D51222.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@341328 91177308-0d34-0410-b5e6-96231b3b80d8
2018-09-03 17:24:23 +00:00
Alexey Bataev 7512891e63 [OPENMP][NVPTX] Replace assert() by ASSERT0() macro, NFC.
Required to fix the buildbots.

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340956 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-29 19:22:06 +00:00
Alexey Bataev 4ae92ac4ef [OPENMP][NVPTX] Lightweight runtime support for SPMD mode.
Summary:
Implemented simple and lightweight runtime support for SPMD mode-based
constructs. It adds support for L2 sequential parallelism wihtout full
runtime support. Also, patch fixes some use cases for
uninitialized|lightweight runtime.

Reviewers: grokos, kkwli0, Hahnfeld, gtbercea

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D51222

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340944 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-29 17:35:09 +00:00
Gheorghe-Teodor Bercea 3e1e7c423b [OpenMP][Fix] Conditional compilation leaves variables unused
Summary: Prevent variables from being left unused by conditional compilation.

Reviewers: ABataev, grokos, Hahnfeld, caomhin, protze.joachim

Reviewed By: Hahnfeld

Subscribers: guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D51303

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340771 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-27 19:54:26 +00:00
Alexandre Eichenberger ba9bfa0f98 [OpenMP][libomptarget] rework of fatal error reporting
Summary:
Removed the function that used a lock and varargs
Used the same mechanism as for debug messages

Reviewers: ABataev, gtbercea, grokos, Hahnfeld

Reviewed By: gtbercea, Hahnfeld

Subscribers: mikerice, ABataev, RaviNarayanaswamy, guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D51226

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340767 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-27 18:20:15 +00:00
Gheorghe-Teodor Bercea e1ad05c6ba [OpenMP][Fix] Ensure comparison between unsigned values.
Summary: Ensure the values being compared are both unsigned.

Reviewers: ABataev, Hahnfeld, caomhin, grokos, AndreyChurbanov

Reviewed By: AndreyChurbanov

Subscribers: AndreyChurbanov, guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D51301

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340745 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-27 14:52:20 +00:00
Jonathan Peyton 9035de6e1c [OpenMP] Remove deprecated/obsolete MIC attributes from headers
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340656 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-24 21:34:10 +00:00
Jonathan Peyton 743b502b93 [OpenMP] Fixed affinity verbose double printing for balanced type.
git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340647 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-24 20:35:42 +00:00
Jonathan Peyton 984dfdcac7 [OpenMP] Fix tasking bug for decreasing hot team nthreads
The __kmp_execute_tasks_template() function reads the task_team and
current_task from the thread structure. There appears to be a pathological
timing where the number of threads in the hot team decreases and so a
thread is put in the pool via __kmp_free_thread(). It could be the case that:
1) A thread reads th_task_team into task_team local variables
       and is then interrupted by the OS
2) Master frees the thread and sets current task and task team to NULL
3) The thread reads current_task as NULL

When this happens, current_task is dereferenced and a segfault occurs.
This patch just checks for current_task to not be NULL as well.

Differential Revision: https://reviews.llvm.org/D50651


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340632 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-24 18:07:35 +00:00
Jonathan Peyton 420cbcd0c4 [OpenMP] Add check for hot_teams array
If hot teams are not being used, this code could seg fault without the added
check, and does so when composability is used in conjunction with nesting.
The fix prevents the segfault.

Differential Revision: https://reviews.llvm.org/D50649


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340629 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-24 18:05:00 +00:00
Jonathan Peyton d9dca06e83 [OpenMP] Fix incorrect barrier imbalance reporting in ITTNOTIFY
Exclude nested explicit tasks from timing, only outer level explicit task
counted and its time added to barrier arrive time for the thread.

Differential Revision: https://reviews.llvm.org/D50584


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340628 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-24 18:03:27 +00:00
Alexandre Eichenberger 95171846cd [OpenMP][libomptarget] Bringing up to spec with respect to OMP_TARGET_OFFLOAD env var
Summary:
Right now, only the OMP_TARGET_OFFLOAD=DISABLED was implemented. Added support for the other MANDATORY and DEFAULT values.


Reviewers: gtbercea, ABataev, grokos, caomhin, Hahnfeld

Reviewed By: Hahnfeld

Subscribers: protze.joachim, gtbercea, AlexEichenberger, RaviNarayanaswamy, Hahnfeld, guansong, openmp-commits

Differential Revision: https://reviews.llvm.org/D50522

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@340542 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-23 16:22:42 +00:00
Joachim Protze 10c8501bb8 [OMPT] Remove OMPT idle callback
The idle callback was removed from the spec as of TR7.
This removes it from the implementation.

Patch provided by Simon Convent

Reviewers: hbae, protze.joachim

Differential Revision: https://reviews.llvm.org/D48362

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@339771 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-15 13:54:28 +00:00
Jonathan Peyton 967f3abd77 [OMPT] Make omp_control_tool() compliant when called from Fortran programs
This change fixes an incorrect behavior of the omp_control_tool function when
called from Fortran applications.  A tool callback function for this event is
supposed to get NULL for the third argument according to the specification, but
the current implementation just passes a garbage value. A possible fix is to use
the OPTIONAL attribute for the third argument.

Patch by Hansang Bae

Differential Revision: https://reviews.llvm.org/D50565


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@339585 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-13 17:26:18 +00:00
Jonathan Peyton 2b9968a2f9 [OpenMP] Cleanup code
This patch cleans up unused functions, variables, sign compare issues, and
addresses some -Warning flags which are now enabled including -Wcast-qual.
Not all the warning flags in LibompHandleFlags.cmake are enabled, but some
are with this patch.

Some __kmp_gtid_from_* macros in kmp.h are switched to static inline functions
which allows us to remove the awkward definition of KMP_DEBUG_ASSERT() and
KMP_ASSERT() macros which used the comma operator. This had to be done for the
innumerable -Wunused-value warnings related to KMP_DEBUG_ASSERT()

Differential Revision: https://reviews.llvm.org/D49105


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@339393 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-09 22:04:30 +00:00
Jonathan Peyton d97a5dfc16 [OpenMP] Fix doacross testing for gcc
This patch adds a test using the doacross clauses in OpenMP and removes gcc from
testing kmp_doacross_check.c which is only testing the kmp rather than the
gomp interface.

Differential Revision: https://reviews.llvm.org/D50014


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@338757 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-02 19:13:07 +00:00
Jonas Hahnfeld f9ac8870bd [OMPT] Disable by default on Windows
This is broken per PR36561 and PR36574, so disable it for now until
somebody interested can take a look. OMPT can still be activated manually
by passing -DLIBOMP_OMPT_SUPPORT=ON during configuration.

Differential Revision: https://reviews.llvm.org/D50086

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@338721 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-02 14:34:08 +00:00
Jonas Hahnfeld 9d379ca627 [tests] Add annotations for taskloop features
Only supported since GCC 6 and Intel 17.0. However GCC 6.3.0 is
crashing on two of the tests, so disable them as well...

Differential Revision: https://reviews.llvm.org/D50085

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@338720 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-02 14:34:03 +00:00
Joachim Protze c6a4932afe [OMPT,tests] Fix taskloop testcase scheduling effects
The taskloop testcase had scheduling effects. Tasks of the taskloop would
sometimes be scheduled before all task were created. The testing is now
split into two phases. First, the task creation on the master is tested,
than the scheduling events of the tasks are tested. Thus, the order of
creation and scheduling events is irrelavant.

Patch by Simon Convent

Reviewed by: protze.joachim, Hahnfeld

Subscribers: openmp-commits

Differential Revision: https://reviews.llvm.org/D50140

git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@338580 91177308-0d34-0410-b5e6-96231b3b80d8
2018-08-01 16:15:18 +00:00
315 changed files with 17805 additions and 15788 deletions
+239 -52
View File
@@ -1,4 +1,241 @@
==============================================================================
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
==============================================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.
==============================================================================
Software from third parties included in the LLVM Project:
==============================================================================
The LLVM Project contains third party software which is under different license
terms. All such code will be identified clearly using at least one of two
mechanisms:
1) It will be in a separate directory tree with its own `LICENSE.txt` or
`LICENSE` file at the top containing the specific license and restrictions
which apply to that software, or
2) It will contain specific license and restriction terms at the top of every
file.
==============================================================================
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
The software contained in this directory tree is dual licensed under both the
University of Illinois "BSD-Like" license and the MIT license. As a user of
@@ -14,7 +251,7 @@ software contained in this directory tree is included below.
University of Illinois/NCSA
Open Source License
Copyright (c) 1997-2016 Intel Corporation
Copyright (c) 1997-2019 Intel Corporation
All rights reserved.
@@ -51,7 +288,7 @@ SOFTWARE.
==============================================================================
Copyright (c) 1997-2016 Intel Corporation
Copyright (c) 1997-2019 Intel Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -122,53 +359,3 @@ conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE.
==============================================================================
ARM Limited
Software Grant License Agreement ("Agreement")
Except for the license granted herein to you, ARM Limited ("ARM") reserves all
right, title, and interest in and to the Software (defined below).
Definition
"Software" means the code and documentation as well as any original work of
authorship, including any modifications or additions to an existing work, that
is intentionally submitted by ARM to llvm.org (http://llvm.org) ("LLVM") for
inclusion in, or documentation of, any of the products owned or managed by LLVM
(the "Work"). For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to LLVM or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems that are
managed by, or on behalf of, LLVM for the purpose of discussing and improving
the Work, but excluding communication that is conspicuously marked otherwise.
1. Grant of Copyright License. Subject to the terms and conditions of this
Agreement, ARM hereby grants to you and to recipients of the Software
distributed by LLVM a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable copyright license to reproduce, prepare derivative
works of, publicly display, publicly perform, sublicense, and distribute the
Software and such derivative works.
2. Grant of Patent License. Subject to the terms and conditions of this
Agreement, ARM hereby grants you and to recipients of the Software
distributed by LLVM a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license
to make, have made, use, offer to sell, sell, import, and otherwise transfer
the Work, where such license applies only to those patent claims licensable
by ARM that are necessarily infringed by ARM's Software alone or by
combination of the Software with the Work to which such Software was
submitted. If any entity institutes patent litigation against ARM or any
other entity (including a cross-claim or counterclaim in a lawsuit) alleging
that ARM's Software, or the Work to which ARM has contributed constitutes
direct or contributory patent infringement, then any patent licenses granted
to that entity under this Agreement for the Software or Work shall terminate
as of the date such litigation is filed.
Unless required by applicable law or agreed to in writing, the software is
provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied, including, without limitation, any warranties or
conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE.
==============================================================================
+7 -14
View File
@@ -133,7 +133,7 @@ Options for all Libraries
Options for ``libomp``
----------------------
**LIBOMP_ARCH** = ``aarch64|arm|i386|mic|mips|mips64|ppc64|ppc64le|x86_64``
**LIBOMP_ARCH** = ``aarch64|arm|i386|mic|mips|mips64|ppc64|ppc64le|x86_64|riscv64``
The default value for this option is chosen based on probing the compiler for
architecture macros (e.g., is ``__x86_64__`` predefined by compiler?).
@@ -141,10 +141,6 @@ Options for ``libomp``
Intel(R) Many Integrated Core Architecture (Intel(R) MIC Architecture) to
build for. This value is ignored if **LIBOMP_ARCH** does not equal ``mic``.
**LIBOMP_OMP_VERSION** = ``50|45|40|30``
OpenMP version to build for. Older versions will disable certain
functionality and entry points.
**LIBOMP_LIB_TYPE** = ``normal|profile|stubs``
Library type can be ``normal``, ``profile``, or ``stubs``.
@@ -192,9 +188,9 @@ Optional Features
multi-node systems where a small ``CACHE_LINE`` setting leads to false sharing.
**LIBOMP_OMPT_SUPPORT** = ``ON|OFF``
Include support for the OpenMP Tools Interface (OMPT).
This option is supported and ``ON`` by default for x86, x86_64, AArch64, and
PPC64 on Linux* and macOS*.
Include support for the OpenMP Tools Interface (OMPT).
This option is supported and ``ON`` by default for x86, x86_64, AArch64,
PPC64 and RISCV64 on Linux* and macOS*.
This option is ``OFF`` if this feature is not supported for the platform.
**LIBOMP_OMPT_OPTIONAL** = ``ON|OFF``
@@ -225,9 +221,6 @@ These flags are **appended**, they do not overwrite any of the preset flags.
**LIBOMP_CPPFLAGS** = <space-separated flags>
Additional C preprocessor flags.
**LIBOMP_CFLAGS** = <space-separated flags>
Additional C compiler flags.
**LIBOMP_CXXFLAGS** = <space-separated flags>
Additional C++ compiler flags.
@@ -325,12 +318,12 @@ Advanced Builds with Various Options
$ cmake -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc -DCMAKE_Fortran_COMPILER=ifort -DLIBOMP_FORTRAN_MODULES=on ..
- Have CMake find the C/C++ compiler and specify additional flags for the C
compiler, preprocessor, and C++ compiler.
- Have CMake find the C/C++ compiler and specify additional flags for the
preprocessor and C++ compiler.
.. code-blocks:: console
$ cmake -DLIBOMP_CFLAGS='-specific-flag' -DLIBOMP_CPPFLAGS='-DNEW_FEATURE=1 -DOLD_FEATURE=0' -DLIBOMP_CXXFLAGS='--one-specific-flag --two-specific-flag' ..
$ cmake -DLIBOMP_CPPFLAGS='-DNEW_FEATURE=1 -DOLD_FEATURE=0' -DLIBOMP_CXXFLAGS='--one-specific-flag --two-specific-flag' ..
- Build the stubs library
+6 -2
View File
@@ -18,8 +18,12 @@ if (NOT OpenMP_Found)
set(OpenMP_CXX_FLAGS "-fopenmp")
endif()
set(C_FLAGS ${flags} ${OpenMP_C_FLAGS})
set(CXX_FLAGS ${flags} ${OpenMP_CXX_FLAGS})
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
set(C_FLAGS "${OpenMP_C_FLAGS} ${CMAKE_THREAD_LIBS_INIT}")
set(CXX_FLAGS "${OpenMP_CXX_FLAGS} ${CMAKE_THREAD_LIBS_INIT}")
# TODO: Implement blockaddress in GlobalISel and remove this flag!
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+22 -3
View File
@@ -1,4 +1,4 @@
if (${OPENMP_STANDALONE_BUILD})
if (OPENMP_STANDALONE_BUILD)
# From HandleLLVMOptions.cmake
function(append_if condition value)
if (${condition})
@@ -9,8 +9,27 @@ if (${OPENMP_STANDALONE_BUILD})
endfunction()
endif()
if (${OPENMP_ENABLE_WERROR})
# MSVC and clang-cl in compatibility mode map -Wall to -Weverything.
# TODO: LLVM adds /W4 instead, check if that works for the OpenMP runtimes.
if (NOT MSVC)
append_if(OPENMP_HAVE_WALL_FLAG "-Wall" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
if (OPENMP_ENABLE_WERROR)
append_if(OPENMP_HAVE_WERROR_FLAG "-Werror" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
endif()
append_if(OPENMP_HAVE_STD_CPP11_FLAG "-std=c++11" CMAKE_CXX_FLAGS)
# Additional warnings that are not enabled by -Wall.
append_if(OPENMP_HAVE_WCAST_QUAL_FLAG "-Wcast-qual" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_if(OPENMP_HAVE_WFORMAT_PEDANTIC_FLAG "-Wformat-pedantic" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_if(OPENMP_HAVE_WIMPLICIT_FALLTHROUGH_FLAG "-Wimplicit-fallthrough" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_if(OPENMP_HAVE_WSIGN_COMPARE_FLAG "-Wsign-compare" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
# Warnings that we want to disable because they are too verbose or fragile.
append_if(OPENMP_HAVE_WNO_EXTRA_FLAG "-Wno-extra" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_if(OPENMP_HAVE_WNO_PEDANTIC_FLAG "-Wno-pedantic" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_if(OPENMP_HAVE_WNO_MAYBE_UNINITIALIZED_FLAG "-Wno-maybe-uninitialized" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
append_if(OPENMP_HAVE_STD_GNUPP11_FLAG "-std=gnu++11" CMAKE_CXX_FLAGS)
if (NOT OPENMP_HAVE_STD_GNUPP11_FLAG)
append_if(OPENMP_HAVE_STD_CPP11_FLAG "-std=c++11" CMAKE_CXX_FLAGS)
endif()
+15 -5
View File
@@ -99,7 +99,7 @@ if (${OPENMP_STANDALONE_BUILD})
# project is built which is too late for detecting the compiler...
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR}/DetectTestCompiler
COMMAND ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/DetectTestCompiler
-DCMAKE_C_COMPILER=${OPENMP_TEST_C_COMPILER}
-DCMAKE_CXX_COMPILER=${OPENMP_TEST_CXX_COMPILER}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/DetectTestCompiler
@@ -120,8 +120,16 @@ else()
set(OPENMP_TEST_COMPILER_VERSION "${LLVM_VERSION}")
set(OPENMP_TEST_COMPILER_VERSION_MAJOR "${LLVM_MAJOR_VERSION}")
set(OPENMP_TEST_COMPILER_VERSION_MAJOR_MINOR "${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}")
# Unfortunately the top-level cmake/config-ix.cmake file mangles CMake's
# CMAKE_THREAD_LIBS_INIT variable from the FindThreads package, so work
# around that, until it is fixed there.
if("${CMAKE_THREAD_LIBS_INIT}" STREQUAL "-lpthread")
set(OPENMP_TEST_COMPILER_THREAD_FLAGS "-pthread")
else()
set(OPENMP_TEST_COMPILER_THREAD_FLAGS "${CMAKE_THREAD_LIBS_INIT}")
endif()
# TODO: Implement blockaddress in GlobalISel and remove this flag!
set(OPENMP_TEST_COMPILER_OPENMP_FLAGS "-fopenmp -fno-experimental-isel")
set(OPENMP_TEST_COMPILER_OPENMP_FLAGS "-fopenmp ${OPENMP_TEST_COMPILER_THREAD_FLAGS} -fno-experimental-isel")
endif()
# Function to set compiler features for use in lit.
@@ -147,7 +155,7 @@ function(add_openmp_testsuite target comment)
return()
endif()
cmake_parse_arguments(ARG "" "" "DEPENDS" ${ARGN})
cmake_parse_arguments(ARG "" "" "DEPENDS;ARGS" ${ARGN})
# EXCLUDE_FROM_ALL excludes the test ${target} out of check-openmp.
if (NOT EXCLUDE_FROM_ALL)
# Register the testsuites and depends for the check-openmp rule.
@@ -156,8 +164,9 @@ function(add_openmp_testsuite target comment)
endif()
if (${OPENMP_STANDALONE_BUILD})
set(LIT_ARGS ${OPENMP_LIT_ARGS} ${ARG_ARGS})
add_custom_target(${target}
COMMAND ${PYTHON_EXECUTABLE} ${OPENMP_LLVM_LIT_EXECUTABLE} ${OPENMP_LIT_ARGS} ${ARG_UNPARSED_ARGUMENTS}
COMMAND ${PYTHON_EXECUTABLE} ${OPENMP_LLVM_LIT_EXECUTABLE} ${LIT_ARGS} ${ARG_UNPARSED_ARGUMENTS}
COMMENT ${comment}
DEPENDS ${ARG_DEPENDS}
${cmake_3_2_USES_TERMINAL}
@@ -166,7 +175,8 @@ function(add_openmp_testsuite target comment)
add_lit_testsuite(${target}
${comment}
${ARG_UNPARSED_ARGUMENTS}
DEPENDS clang clang-headers FileCheck ${ARG_DEPENDS}
DEPENDS clang clang-resource-headers FileCheck ${ARG_DEPENDS}
ARGS ${ARG_ARGS}
)
endif()
endfunction()
+15 -3
View File
@@ -1,6 +1,18 @@
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
check_c_compiler_flag(-Werror OPENMP_HAVE_WERROR_FLAG)
check_cxx_compiler_flag(-Wall OPENMP_HAVE_WALL_FLAG)
check_cxx_compiler_flag(-Werror OPENMP_HAVE_WERROR_FLAG)
check_cxx_compiler_flag(-std=c++11 OPENMP_HAVE_STD_CPP11_FLAG)
# Additional warnings that are not enabled by -Wall.
check_cxx_compiler_flag(-Wcast-qual OPENMP_HAVE_WCAST_QUAL_FLAG)
check_cxx_compiler_flag(-Wformat-pedantic OPENMP_HAVE_WFORMAT_PEDANTIC_FLAG)
check_cxx_compiler_flag(-Wimplicit-fallthrough OPENMP_HAVE_WIMPLICIT_FALLTHROUGH_FLAG)
check_cxx_compiler_flag(-Wsign-compare OPENMP_HAVE_WSIGN_COMPARE_FLAG)
# Warnings that we want to disable because they are too verbose or fragile.
check_cxx_compiler_flag(-Wno-extra OPENMP_HAVE_WNO_EXTRA_FLAG)
check_cxx_compiler_flag(-Wno-pedantic OPENMP_HAVE_WNO_PEDANTIC_FLAG)
check_cxx_compiler_flag(-Wno-maybe-uninitialized OPENMP_HAVE_WNO_MAYBE_UNINITIALIZED_FLAG)
check_cxx_compiler_flag(-std=gnu++11 OPENMP_HAVE_STD_GNUPP11_FLAG)
check_cxx_compiler_flag(-std=c++11 OPENMP_HAVE_STD_CPP11_FLAG)
+23 -12
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
@@ -20,6 +19,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules ${CMAKE_MODULE_P
if(OPENMP_STANDALONE_BUILD)
# Build all libraries into a common place so that tests can find them.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
@@ -40,17 +40,17 @@ set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda")
# the list of supported targets in the current system.
set (LIBOMPTARGET_SYSTEM_TARGETS "")
# Set base directories - required for lit to locate the tests.
set(LIBOMPTARGET_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBOMPTARGET_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# If building this library in debug mode, we define a macro to enable
# dumping progress messages at runtime.
# Check whether using debug mode. In debug mode, allow dumping progress
# messages at runtime by default. Otherwise, it can be enabled
# independently using the LIBOMPTARGET_ENABLE_DEBUG option.
string( TOLOWER "${CMAKE_BUILD_TYPE}" LIBOMPTARGET_CMAKE_BUILD_TYPE)
if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
option(LIBOMPTARGET_ENABLE_DEBUG "Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1" ON)
else()
option(LIBOMPTARGET_ENABLE_DEBUG "Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1" OFF)
endif()
if(LIBOMPTARGET_ENABLE_DEBUG)
add_definitions(-DOMPTARGET_DEBUG)
add_definitions(-g)
add_definitions(-O0)
endif()
include_directories(include)
@@ -65,6 +65,17 @@ if(NOT LIBOMPTARGET_LIBRARY_DIR)
set(LIBOMPTARGET_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Definitions for testing, for reuse when testing libomptarget-nvptx.
if(OPENMP_STANDALONE_BUILD)
set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../runtime/src" CACHE STRING
"Path to folder containing omp.h")
set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../runtime/src" CACHE STRING
"Path to folder containing libomp.so")
else()
set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../runtime/src")
endif()
# Build offloading plugins and device RTLs if they are available.
add_subdirectory(plugins)
add_subdirectory(deviceRTLs)
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -112,6 +111,9 @@ mark_as_advanced(
################################################################################
# Looking for CUDA...
################################################################################
if (CUDA_TOOLKIT_ROOT_DIR)
set(LIBOMPTARGET_CUDA_TOOLKIT_ROOT_DIR_PRESET TRUE)
endif()
find_package(CUDA QUIET)
set(LIBOMPTARGET_DEP_CUDA_FOUND ${CUDA_FOUND})
@@ -158,3 +160,33 @@ find_package_handle_standard_args(
LIBOMPTARGET_DEP_CUDA_DRIVER_LIBRARIES)
mark_as_advanced(LIBOMPTARGET_DEP_CUDA_DRIVER_LIBRARIES)
################################################################################
# Looking for CUDA libdevice subdirectory
#
# Special case for Debian/Ubuntu to have nvidia-cuda-toolkit work
# out of the box. More info on http://bugs.debian.org/882505
################################################################################
set(LIBOMPTARGET_CUDA_LIBDEVICE_SUBDIR nvvm/libdevice)
# Don't alter CUDA_TOOLKIT_ROOT_DIR if the user specified it, if a value was
# already cached for it, or if it already has libdevice. Otherwise, on
# Debian/Ubuntu, look where the nvidia-cuda-toolkit package normally installs
# libdevice.
if (NOT LIBOMPTARGET_CUDA_TOOLKIT_ROOT_DIR_PRESET AND
NOT EXISTS
"${CUDA_TOOLKIT_ROOT_DIR}/${LIBOMPTARGET_CUDA_LIBDEVICE_SUBDIR}")
find_program(LSB_RELEASE lsb_release)
if (LSB_RELEASE)
execute_process(COMMAND ${LSB_RELEASE} -is
OUTPUT_VARIABLE LSB_RELEASE_ID
OUTPUT_STRIP_TRAILING_WHITESPACE)
set(candidate_dir /usr/lib/cuda)
if ((LSB_RELEASE_ID STREQUAL "Debian" OR LSB_RELEASE_ID STREQUAL "Ubuntu")
AND EXISTS "${candidate_dir}/${LIBOMPTARGET_CUDA_LIBDEVICE_SUBDIR}")
set(CUDA_TOOLKIT_ROOT_DIR "${candidate_dir}" CACHE PATH
"Toolkit location." FORCE)
endif()
endif()
endif()
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -79,7 +78,7 @@ endfunction()
# These flags are required to emit LLVM Bitcode. We check them together because
# if any of them are not supported, there is no point in finding out which are.
set(compiler_flags_required -emit-llvm -O1 --cuda-device-only --cuda-path=${CUDA_TOOLKIT_ROOT_DIR})
set(compiler_flags_required -emit-llvm -O1 --cuda-device-only -std=c++11 --cuda-path=${CUDA_TOOLKIT_ROOT_DIR})
set(compiler_flags_required_src "extern \"C\" __device__ int thread() { return threadIdx.x; }")
check_bitcode_compilation(LIBOMPTARGET_NVPTX_CUDA_COMPILER_SUPPORTS_FLAGS_REQUIRED "${compiler_flags_required_src}" ${compiler_flags_required})
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
+3 -4
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ##===----------------------------------------------------------------------===##
#
@@ -1,18 +1,14 @@
//===------- interface.h - NVPTX OpenMP interface definitions ---- CUDA -*-===//
//===------- interface.h - OpenMP interface definitions ---------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains debug macros to be used in the application.
//
// This file contains all the definitions that are relevant to
// the interface. The first section contains the interface as
// declared by OpenMP. A second section includes library private calls
// (mostly debug, temporary?) The third section includes the compiler
// declared by OpenMP. The second section includes the compiler
// specific interfaces.
//
//===----------------------------------------------------------------------===//
@@ -20,6 +16,12 @@
#ifndef _INTERFACES_H_
#define _INTERFACES_H_
#include <stdint.h>
#ifdef __CUDACC__
#include "nvptx/src/nvptx_interface.h"
#endif
////////////////////////////////////////////////////////////////////////////////
// OpenMP interface
////////////////////////////////////////////////////////////////////////////////
@@ -88,18 +90,6 @@ EXTERN int omp_is_initial_device(void);
EXTERN int omp_get_initial_device(void);
EXTERN int omp_get_max_task_priority(void);
////////////////////////////////////////////////////////////////////////////////
// OMPTARGET_NVPTX private (debug / temportary?) interface
////////////////////////////////////////////////////////////////////////////////
// for debug
EXTERN void __kmpc_print_str(char *title);
EXTERN void __kmpc_print_title_int(char *title, int data);
EXTERN void __kmpc_print_index(char *title, int i);
EXTERN void __kmpc_print_int(int data);
EXTERN void __kmpc_print_double(double data);
EXTERN void __kmpc_print_address_int64(int64_t data);
////////////////////////////////////////////////////////////////////////////////
// file below is swiped from kmpc host interface
////////////////////////////////////////////////////////////////////////////////
@@ -116,6 +106,8 @@ typedef enum kmp_sched_t {
kmp_sched_runtime = 37,
kmp_sched_auto = 38,
kmp_sched_static_balanced_chunk = 45,
kmp_sched_static_ordered = 65,
kmp_sched_static_nochunk_ordered = 66,
kmp_sched_dynamic_ordered = 67,
@@ -168,8 +160,36 @@ typedef enum kmp_sched_t {
} kmp_sched_t;
/*!
* Enum for accesseing the reserved_2 field of the ident_t struct below.
*/
enum {
/*! Bit set to 1 when in SPMD mode. */
KMP_IDENT_SPMD_MODE = 0x01,
/*! Bit set to 1 when a simplified runtime is used. */
KMP_IDENT_SIMPLE_RT_MODE = 0x02,
};
/*!
* The ident structure that describes a source location.
* The struct is identical to the one in the kmp.h file.
* We maintain the same data structure for compatibility.
*/
typedef int kmp_int32;
typedef struct ident {
kmp_int32 reserved_1; /**< might be used in Fortran; see above */
kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; KMP_IDENT_KMPC
identifies this union member */
kmp_int32 reserved_2; /**< not really used in Fortran any more; see above */
kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for C++ */
char const *psource; /**< String describing the source location.
The string is composed of semi-colon separated fields
which describe the source file, the function and a pair
of line numbers that delimit the construct. */
} ident_t;
// parallel defs
typedef void kmp_Indent;
typedef ident_t kmp_Ident;
typedef void (*kmp_ParFctPtr)(int32_t *global_tid, int32_t *bound_tid, ...);
typedef void (*kmp_ReductFctPtr)(void *lhsData, void *rhsData);
typedef void (*kmp_InterWarpCopyFctPtr)(void *src, int32_t warp_num);
@@ -181,6 +201,7 @@ typedef void (*kmp_CopyToScratchpadFctPtr)(void *reduceData, void *scratchpad,
typedef void (*kmp_LoadReduceFctPtr)(void *reduceData, void *scratchpad,
int32_t index, int32_t width,
int32_t reduce);
typedef void (*kmp_ListGlobalFctPtr)(void *buffer, int idx, void *reduce_data);
// task defs
typedef struct kmp_TaskDescr kmp_TaskDescr;
@@ -191,68 +212,31 @@ typedef struct kmp_TaskDescr {
int32_t partId; // unused
kmp_TaskFctPtr destructors; // destructor of c++ first private
} kmp_TaskDescr;
// task dep defs
#define KMP_TASKDEP_IN 0x1u
#define KMP_TASKDEP_OUT 0x2u
typedef struct kmp_TaskDep_Public {
void *addr;
size_t len;
uint8_t flags; // bit 0: in, bit 1: out
} kmp_TaskDep_Public;
// flags that interpret the interface part of tasking flags
#define KMP_TASK_IS_TIED 0x1
#define KMP_TASK_FINAL 0x2
#define KMP_TASK_MERGED_IF0 0x4 /* unused */
#define KMP_TASK_DESTRUCTOR_THUNK 0x8
// flags for task setup return
#define KMP_CURRENT_TASK_NOT_SUSPENDED 0
#define KMP_CURRENT_TASK_SUSPENDED 1
// sync defs
typedef int32_t kmp_CriticalName[8];
////////////////////////////////////////////////////////////////////////////////
// flags for kstate (all bits initially off)
////////////////////////////////////////////////////////////////////////////////
// first 2 bits used by kmp_Reduction (defined in kmp_reduction.cpp)
#define KMP_REDUCTION_MASK 0x3
#define KMP_SKIP_NEXT_CALL 0x4
#define KMP_SKIP_NEXT_CANCEL_BARRIER 0x8
////////////////////////////////////////////////////////////////////////////////
// data
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// external interface
////////////////////////////////////////////////////////////////////////////////
// query
EXTERN int32_t __kmpc_global_num_threads(kmp_Indent *loc); // missing
EXTERN int32_t __kmpc_bound_thread_num(kmp_Indent *loc); // missing
EXTERN int32_t __kmpc_bound_num_threads(kmp_Indent *loc); // missing
EXTERN int32_t __kmpc_in_parallel(kmp_Indent *loc); // missing
// parallel
EXTERN int32_t __kmpc_global_thread_num(kmp_Indent *loc);
EXTERN void __kmpc_push_num_threads(kmp_Indent *loc, int32_t global_tid,
EXTERN int32_t __kmpc_global_thread_num(kmp_Ident *loc);
EXTERN void __kmpc_push_num_threads(kmp_Ident *loc, int32_t global_tid,
int32_t num_threads);
// simd
EXTERN void __kmpc_push_simd_limit(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_push_simd_limit(kmp_Ident *loc, int32_t global_tid,
int32_t simd_limit);
// aee ... not supported
// EXTERN void __kmpc_fork_call(kmp_Indent *loc, int32_t argc, kmp_ParFctPtr
// EXTERN void __kmpc_fork_call(kmp_Ident *loc, int32_t argc, kmp_ParFctPtr
// microtask, ...);
EXTERN void __kmpc_serialized_parallel(kmp_Indent *loc, uint32_t global_tid);
EXTERN void __kmpc_end_serialized_parallel(kmp_Indent *loc,
EXTERN void __kmpc_serialized_parallel(kmp_Ident *loc, uint32_t global_tid);
EXTERN void __kmpc_end_serialized_parallel(kmp_Ident *loc,
uint32_t global_tid);
EXTERN uint16_t __kmpc_parallel_level(kmp_Indent *loc, uint32_t global_tid);
EXTERN uint16_t __kmpc_parallel_level(kmp_Ident *loc, uint32_t global_tid);
// proc bind
EXTERN void __kmpc_push_proc_bind(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_push_proc_bind(kmp_Ident *loc, uint32_t global_tid,
int proc_bind);
EXTERN int omp_get_num_places(void);
EXTERN int omp_get_place_num_procs(int place_num);
@@ -262,52 +246,52 @@ EXTERN int omp_get_partition_num_places(void);
EXTERN void omp_get_partition_place_nums(int *place_nums);
// for static (no chunk or chunk)
EXTERN void __kmpc_for_static_init_4(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_4(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter,
int32_t *plower, int32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk);
EXTERN void __kmpc_for_static_init_4u(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_4u(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter,
uint32_t *plower, uint32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk);
EXTERN void __kmpc_for_static_init_8(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_8(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter,
int64_t *plower, int64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk);
EXTERN void __kmpc_for_static_init_8u(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_8u(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter1,
uint64_t *plower, uint64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk);
EXTERN
void __kmpc_for_static_init_4_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_4_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter,
int32_t *plower, int32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk);
EXTERN
void __kmpc_for_static_init_4u_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_4u_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter,
uint32_t *plower, uint32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk);
EXTERN
void __kmpc_for_static_init_8_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_8_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter,
int64_t *plower, int64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk);
EXTERN
void __kmpc_for_static_init_8u_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_8u_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t *plastiter1,
uint64_t *plower, uint64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk);
EXTERN
void __kmpc_for_static_init_4_simple_generic(kmp_Indent *loc,
void __kmpc_for_static_init_4_simple_generic(kmp_Ident *loc,
int32_t global_tid, int32_t sched,
int32_t *plastiter,
int32_t *plower, int32_t *pupper,
@@ -315,11 +299,11 @@ void __kmpc_for_static_init_4_simple_generic(kmp_Indent *loc,
int32_t chunk);
EXTERN
void __kmpc_for_static_init_4u_simple_generic(
kmp_Indent *loc, int32_t global_tid, int32_t sched, int32_t *plastiter,
kmp_Ident *loc, int32_t global_tid, int32_t sched, int32_t *plastiter,
uint32_t *plower, uint32_t *pupper, int32_t *pstride, int32_t incr,
int32_t chunk);
EXTERN
void __kmpc_for_static_init_8_simple_generic(kmp_Indent *loc,
void __kmpc_for_static_init_8_simple_generic(kmp_Ident *loc,
int32_t global_tid, int32_t sched,
int32_t *plastiter,
int64_t *plower, int64_t *pupper,
@@ -327,57 +311,61 @@ void __kmpc_for_static_init_8_simple_generic(kmp_Indent *loc,
int64_t chunk);
EXTERN
void __kmpc_for_static_init_8u_simple_generic(
kmp_Indent *loc, int32_t global_tid, int32_t sched, int32_t *plastiter1,
kmp_Ident *loc, int32_t global_tid, int32_t sched, int32_t *plastiter1,
uint64_t *plower, uint64_t *pupper, int64_t *pstride, int64_t incr,
int64_t chunk);
EXTERN void __kmpc_for_static_fini(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_for_static_fini(kmp_Ident *loc, int32_t global_tid);
// for dynamic
EXTERN void __kmpc_dispatch_init_4(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_dispatch_init_4(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int32_t lower, int32_t upper,
int32_t incr, int32_t chunk);
EXTERN void __kmpc_dispatch_init_4u(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_dispatch_init_4u(kmp_Ident *loc, int32_t global_tid,
int32_t sched, uint32_t lower,
uint32_t upper, int32_t incr,
int32_t chunk);
EXTERN void __kmpc_dispatch_init_8(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_dispatch_init_8(kmp_Ident *loc, int32_t global_tid,
int32_t sched, int64_t lower, int64_t upper,
int64_t incr, int64_t chunk);
EXTERN void __kmpc_dispatch_init_8u(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_dispatch_init_8u(kmp_Ident *loc, int32_t global_tid,
int32_t sched, uint64_t lower,
uint64_t upper, int64_t incr,
int64_t chunk);
EXTERN int __kmpc_dispatch_next_4(kmp_Indent *loc, int32_t global_tid,
EXTERN int __kmpc_dispatch_next_4(kmp_Ident *loc, int32_t global_tid,
int32_t *plastiter, int32_t *plower,
int32_t *pupper, int32_t *pstride);
EXTERN int __kmpc_dispatch_next_4u(kmp_Indent *loc, int32_t global_tid,
EXTERN int __kmpc_dispatch_next_4u(kmp_Ident *loc, int32_t global_tid,
int32_t *plastiter, uint32_t *plower,
uint32_t *pupper, int32_t *pstride);
EXTERN int __kmpc_dispatch_next_8(kmp_Indent *loc, int32_t global_tid,
EXTERN int __kmpc_dispatch_next_8(kmp_Ident *loc, int32_t global_tid,
int32_t *plastiter, int64_t *plower,
int64_t *pupper, int64_t *pstride);
EXTERN int __kmpc_dispatch_next_8u(kmp_Indent *loc, int32_t global_tid,
EXTERN int __kmpc_dispatch_next_8u(kmp_Ident *loc, int32_t global_tid,
int32_t *plastiter, uint64_t *plower,
uint64_t *pupper, int64_t *pstride);
EXTERN void __kmpc_dispatch_fini_4(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_4u(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_8(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_8u(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_4(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_4u(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_8(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_dispatch_fini_8u(kmp_Ident *loc, int32_t global_tid);
// Support for reducing conditional lastprivate variables
EXTERN void __kmpc_reduce_conditional_lastprivate(kmp_Indent *loc,
EXTERN void __kmpc_reduce_conditional_lastprivate(kmp_Ident *loc,
int32_t global_tid,
int32_t varNum, void *array);
// reduction
EXTERN void __kmpc_nvptx_end_reduce(int32_t global_tid);
EXTERN void __kmpc_nvptx_end_reduce_nowait(int32_t global_tid);
EXTERN int32_t __kmpc_nvptx_parallel_reduce_nowait(
EXTERN __attribute__((deprecated)) int32_t __kmpc_nvptx_parallel_reduce_nowait(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct);
EXTERN int32_t __kmpc_nvptx_parallel_reduce_nowait_v2(
kmp_Ident *loc, int32_t global_tid, int32_t num_vars, size_t reduce_size,
void *reduce_data, kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct);
EXTERN int32_t __kmpc_nvptx_parallel_reduce_nowait_simple_spmd(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct);
@@ -387,6 +375,12 @@ EXTERN int32_t __kmpc_nvptx_parallel_reduce_nowait_simple_generic(
EXTERN int32_t __kmpc_nvptx_simd_reduce_nowait(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct);
EXTERN int32_t __kmpc_nvptx_teams_reduce_nowait_v2(
kmp_Ident *loc, int32_t global_tid, void *global_buffer,
int32_t num_of_records, void *reduce_data, kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct, kmp_ListGlobalFctPtr lgcpyFct,
kmp_ListGlobalFctPtr lgredFct, kmp_ListGlobalFctPtr glcpyFct,
kmp_ListGlobalFctPtr glredFct);
EXTERN int32_t __kmpc_nvptx_teams_reduce_nowait(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct,
@@ -399,67 +393,75 @@ EXTERN int32_t __kmpc_nvptx_teams_reduce_nowait_simple_generic(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct,
kmp_CopyToScratchpadFctPtr sratchFct, kmp_LoadReduceFctPtr ldFct);
EXTERN int32_t __kmpc_nvptx_teams_reduce_nowait_simple(kmp_Ident *loc,
int32_t global_tid,
kmp_CriticalName *crit);
EXTERN void __kmpc_nvptx_teams_end_reduce_nowait_simple(kmp_Ident *loc,
int32_t global_tid,
kmp_CriticalName *crit);
EXTERN int32_t __kmpc_shuffle_int32(int32_t val, int16_t delta, int16_t size);
EXTERN int64_t __kmpc_shuffle_int64(int64_t val, int16_t delta, int16_t size);
// sync barrier
EXTERN void __kmpc_barrier(kmp_Indent *loc_ref, int32_t tid);
EXTERN void __kmpc_barrier_simple_spmd(kmp_Indent *loc_ref, int32_t tid);
EXTERN void __kmpc_barrier_simple_generic(kmp_Indent *loc_ref, int32_t tid);
EXTERN int32_t __kmpc_cancel_barrier(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_barrier(kmp_Ident *loc_ref, int32_t tid);
EXTERN void __kmpc_barrier_simple_spmd(kmp_Ident *loc_ref, int32_t tid);
EXTERN void __kmpc_barrier_simple_generic(kmp_Ident *loc_ref, int32_t tid);
EXTERN int32_t __kmpc_cancel_barrier(kmp_Ident *loc, int32_t global_tid);
// single
EXTERN int32_t __kmpc_single(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_end_single(kmp_Indent *loc, int32_t global_tid);
EXTERN int32_t __kmpc_single(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_end_single(kmp_Ident *loc, int32_t global_tid);
// sync
EXTERN int32_t __kmpc_master(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_end_master(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_ordered(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_end_ordered(kmp_Indent *loc, int32_t global_tid);
EXTERN void __kmpc_critical(kmp_Indent *loc, int32_t global_tid,
EXTERN int32_t __kmpc_master(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_end_master(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_ordered(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_end_ordered(kmp_Ident *loc, int32_t global_tid);
EXTERN void __kmpc_critical(kmp_Ident *loc, int32_t global_tid,
kmp_CriticalName *crit);
EXTERN void __kmpc_end_critical(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_end_critical(kmp_Ident *loc, int32_t global_tid,
kmp_CriticalName *crit);
EXTERN void __kmpc_flush(kmp_Indent *loc);
EXTERN void __kmpc_flush(kmp_Ident *loc);
// vote
EXTERN int32_t __kmpc_warp_active_thread_mask();
EXTERN __kmpc_impl_lanemask_t __kmpc_warp_active_thread_mask();
// syncwarp
EXTERN void __kmpc_syncwarp(__kmpc_impl_lanemask_t);
// tasks
EXTERN kmp_TaskDescr *__kmpc_omp_task_alloc(kmp_Indent *loc,
EXTERN kmp_TaskDescr *__kmpc_omp_task_alloc(kmp_Ident *loc,
uint32_t global_tid, int32_t flag,
size_t sizeOfTaskInclPrivate,
size_t sizeOfSharedTable,
kmp_TaskFctPtr sub);
EXTERN int32_t __kmpc_omp_task(kmp_Indent *loc, uint32_t global_tid,
EXTERN int32_t __kmpc_omp_task(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newLegacyTaskDescr);
EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Indent *loc, uint32_t global_tid,
EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newLegacyTaskDescr,
int32_t depNum, void *depList,
int32_t noAliasDepNum,
void *noAliasDepList);
EXTERN void __kmpc_omp_task_begin_if0(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_omp_task_begin_if0(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newLegacyTaskDescr);
EXTERN void __kmpc_omp_task_complete_if0(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_omp_task_complete_if0(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newLegacyTaskDescr);
EXTERN void __kmpc_omp_wait_deps(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_omp_wait_deps(kmp_Ident *loc, uint32_t global_tid,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList);
EXTERN void __kmpc_taskgroup(kmp_Indent *loc, uint32_t global_tid);
EXTERN void __kmpc_end_taskgroup(kmp_Indent *loc, uint32_t global_tid);
EXTERN int32_t __kmpc_omp_taskyield(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_taskgroup(kmp_Ident *loc, uint32_t global_tid);
EXTERN void __kmpc_end_taskgroup(kmp_Ident *loc, uint32_t global_tid);
EXTERN int32_t __kmpc_omp_taskyield(kmp_Ident *loc, uint32_t global_tid,
int end_part);
EXTERN int32_t __kmpc_omp_taskwait(kmp_Indent *loc, uint32_t global_tid);
EXTERN void __kmpc_taskloop(kmp_Indent *loc, uint32_t global_tid,
EXTERN int32_t __kmpc_omp_taskwait(kmp_Ident *loc, uint32_t global_tid);
EXTERN void __kmpc_taskloop(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newKmpTaskDescr, int if_val,
uint64_t *lb, uint64_t *ub, int64_t st, int nogroup,
int32_t sched, uint64_t grainsize, void *task_dup);
// cancel
EXTERN int32_t __kmpc_cancellationpoint(kmp_Indent *loc, int32_t global_tid,
EXTERN int32_t __kmpc_cancellationpoint(kmp_Ident *loc, int32_t global_tid,
int32_t cancelVal);
EXTERN int32_t __kmpc_cancel(kmp_Indent *loc, int32_t global_tid,
EXTERN int32_t __kmpc_cancel(kmp_Ident *loc, int32_t global_tid,
int32_t cancelVal);
// non standard
@@ -468,17 +470,20 @@ EXTERN void __kmpc_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime);
EXTERN void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized);
EXTERN void __kmpc_spmd_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime,
int16_t RequiresDataSharing);
EXTERN void __kmpc_spmd_kernel_deinit();
EXTERN __attribute__((deprecated)) void __kmpc_spmd_kernel_deinit();
EXTERN void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime);
EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn,
int16_t IsOMPRuntimeInitialized);
EXTERN bool __kmpc_kernel_parallel(void **WorkFn,
int16_t IsOMPRuntimeInitialized);
EXTERN void __kmpc_kernel_end_parallel();
EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer, uint32_t Mask,
EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer,
__kmpc_impl_lanemask_t Mask,
bool *IsFinal,
int32_t *LaneSource);
EXTERN void __kmpc_kernel_end_convergent_parallel(void *buffer);
EXTERN bool __kmpc_kernel_convergent_simd(void *buffer, uint32_t Mask,
EXTERN bool __kmpc_kernel_convergent_simd(void *buffer,
__kmpc_impl_lanemask_t Mask,
bool *IsFinal, int32_t *LaneSource,
int32_t *LaneId, int32_t *NumLanes);
EXTERN void __kmpc_kernel_end_convergent_simd(void *buffer);
@@ -486,6 +491,8 @@ EXTERN void __kmpc_kernel_end_convergent_simd(void *buffer);
EXTERN void __kmpc_data_sharing_init_stack();
EXTERN void __kmpc_data_sharing_init_stack_spmd();
EXTERN void *__kmpc_data_sharing_coalesced_push_stack(size_t size,
int16_t UseSharedMemory);
EXTERN void *__kmpc_data_sharing_push_stack(size_t size, int16_t UseSharedMemory);
EXTERN void __kmpc_data_sharing_pop_stack(void *a);
EXTERN void __kmpc_begin_sharing_variables(void ***GlobalArgs, size_t nArgs);
@@ -507,12 +514,13 @@ __kmpc_initialize_data_sharing_environment(__kmpc_data_sharing_slot *RootS,
size_t InitialDataSize);
EXTERN void *__kmpc_data_sharing_environment_begin(
__kmpc_data_sharing_slot **SavedSharedSlot, void **SavedSharedStack,
void **SavedSharedFrame, int32_t *SavedActiveThreads,
void **SavedSharedFrame, __kmpc_impl_lanemask_t *SavedActiveThreads,
size_t SharingDataSize, size_t SharingDefaultDataSize,
int16_t IsOMPRuntimeInitialized);
EXTERN void __kmpc_data_sharing_environment_end(
__kmpc_data_sharing_slot **SavedSharedSlot, void **SavedSharedStack,
void **SavedSharedFrame, int32_t *SavedActiveThreads, int32_t IsEntryPoint);
void **SavedSharedFrame, __kmpc_impl_lanemask_t *SavedActiveThreads,
int32_t IsEntryPoint);
EXTERN void *
__kmpc_get_data_sharing_environment_frame(int32_t SourceThreadID,
@@ -520,4 +528,12 @@ __kmpc_get_data_sharing_environment_frame(int32_t SourceThreadID,
// SPMD execution mode interrogation function.
EXTERN int8_t __kmpc_is_spmd_exec_mode();
EXTERN void __kmpc_get_team_static_memory(int16_t isSPMDExecutionMode,
const void *buf, size_t size,
int16_t is_shared, const void **res);
EXTERN void __kmpc_restore_team_static_memory(int16_t isSPMDExecutionMode,
int16_t is_shared);
#endif
+15 -6
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
@@ -36,6 +35,10 @@ if(CUDA_HOST_COMPILER MATCHES clang)
set(CUDA_HOST_COMPILER "${LIBOMPTARGET_NVPTX_ALTERNATE_GCC_HOST_COMPILER}" CACHE FILEPATH "" FORCE)
endif()
get_filename_component(devicertl_base_directory
${CMAKE_CURRENT_SOURCE_DIR}
DIRECTORY)
if(LIBOMPTARGET_DEP_CUDA_FOUND)
libomptarget_say("Building CUDA offloading device RTL.")
@@ -84,7 +87,7 @@ if(LIBOMPTARGET_DEP_CUDA_FOUND)
# yet supported by the CUDA toolchain on the device.
set(BUILD_SHARED_LIBS OFF)
set(CUDA_SEPARABLE_COMPILATION ON)
list(APPEND CUDA_NVCC_FLAGS -I${devicertl_base_directory})
cuda_add_library(omptarget-nvptx STATIC ${cuda_src_files} ${omp_data_objects}
OPTIONS ${CUDA_ARCH} ${CUDA_DEBUG})
@@ -118,7 +121,8 @@ if(LIBOMPTARGET_DEP_CUDA_FOUND)
libomptarget_say("Building CUDA LLVM bitcode offloading device RTL.")
# Set flags for LLVM Bitcode compilation.
set(bc_flags ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS} -DOMPTARGET_NVPTX_TEST=0)
set(bc_flags ${LIBOMPTARGET_NVPTX_SELECTED_CUDA_COMPILER_FLAGS}
-I${devicertl_base_directory})
if(${LIBOMPTARGET_NVPTX_DEBUG})
set(bc_flags ${bc_flags} -DOMPTARGET_NVPTX_DEBUG=-1)
else()
@@ -132,6 +136,9 @@ if(LIBOMPTARGET_DEP_CUDA_FOUND)
set(bc_flags ${bc_flags} -Dnv_weak=weak)
endif()
# Create target to build all Bitcode libraries.
add_custom_target(omptarget-nvptx-bc)
# Generate a Bitcode library for all the compute capabilities the user requested.
foreach(sm ${nvptx_sm_list})
set(cuda_arch --cuda-gpu-arch=sm_${sm})
@@ -165,6 +172,7 @@ if(LIBOMPTARGET_DEP_CUDA_FOUND)
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES libomptarget-nvptx-sm_${sm}.bc)
add_custom_target(omptarget-nvptx-${sm}-bc ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/libomptarget-nvptx-sm_${sm}.bc)
add_dependencies(omptarget-nvptx-bc omptarget-nvptx-${sm}-bc)
# Copy library to destination.
add_custom_command(TARGET omptarget-nvptx-${sm}-bc POST_BUILD
@@ -176,6 +184,7 @@ if(LIBOMPTARGET_DEP_CUDA_FOUND)
endforeach()
endif()
add_subdirectory(test)
else()
libomptarget_say("Not building CUDA offloading device RTL: CUDA tools not found in the system.")
endif()
+7 -8
View File
@@ -1,9 +1,8 @@
//===------ cancel.cu - NVPTX OpenMP cancel interface ------------ CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -13,16 +12,16 @@
#include "omptarget-nvptx.h"
EXTERN int32_t __kmpc_cancellationpoint(kmp_Indent *loc, int32_t global_tid,
EXTERN int32_t __kmpc_cancellationpoint(kmp_Ident *loc, int32_t global_tid,
int32_t cancelVal) {
PRINT(LD_IO, "call kmpc_cancellationpoint(cancel val %d)\n", cancelVal);
PRINT(LD_IO, "call kmpc_cancellationpoint(cancel val %d)\n", (int)cancelVal);
// disabled
return FALSE;
}
EXTERN int32_t __kmpc_cancel(kmp_Indent *loc, int32_t global_tid,
EXTERN int32_t __kmpc_cancel(kmp_Ident *loc, int32_t global_tid,
int32_t cancelVal) {
PRINT(LD_IO, "call kmpc_cancel(cancel val %d)\n", cancelVal);
PRINT(LD_IO, "call kmpc_cancel(cancel val %d)\n", (int)cancelVal);
// disabled
return FALSE;
}
@@ -1,51 +0,0 @@
//===------ counter_group.h - NVPTX OpenMP loop scheduling ------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//
//
// Interface to implement OpenMP loop scheduling
//
//===----------------------------------------------------------------------===//
#ifndef _OMPTARGET_NVPTX_COUNTER_GROUP_H_
#define _OMPTARGET_NVPTX_COUNTER_GROUP_H_
#include "option.h"
// counter group type for synchronizations
class omptarget_nvptx_CounterGroup {
public:
// getters and setters
INLINE Counter &Event() { return v_event; }
INLINE volatile Counter &Start() { return v_start; }
INLINE Counter &Init() { return v_init; }
// Synchronization Interface
INLINE void Clear(); // first time start=event
INLINE void Reset(); // init = first
INLINE void Init(Counter &priv); // priv = init
INLINE Counter Next(); // just counts number of events
// set priv to n, to be used in later waitOrRelease
INLINE void Complete(Counter &priv, Counter n);
// check priv and decide if we have to wait or can free the other warps
INLINE void Release(Counter priv, Counter current_event_value);
INLINE void WaitOrRelease(Counter priv, Counter current_event_value);
private:
Counter v_event; // counter of events (atomic)
// volatile is needed to force loads to read from global
// memory or L2 cache and see the write by the last master
volatile Counter v_start; // signal when events registered are finished
Counter v_init; // used to initialize local thread variables
};
#endif /* SRC_COUNTER_GROUP_H_ */
@@ -1,82 +0,0 @@
//===----- counter_groupi.h - NVPTX OpenMP loop scheduling ------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//
//
// Interface implementation for OpenMP loop scheduling
//
//===----------------------------------------------------------------------===//
#include "option.h"
INLINE void omptarget_nvptx_CounterGroup::Clear() {
PRINT0(LD_SYNCD, "clear counters\n")
v_event = 0;
v_start = 0;
// v_init does not need to be reset (its value is dead)
}
INLINE void omptarget_nvptx_CounterGroup::Reset() {
// done by master before entering parallel
ASSERT(LT_FUSSY, v_event == v_start,
"error, entry %lld !=start %lld at reset\n", P64(v_event),
P64(v_start));
v_init = v_start;
}
INLINE void omptarget_nvptx_CounterGroup::Init(Counter &priv) {
PRINT(LD_SYNCD, "init priv counter 0x%llx with val %lld\n", P64(&priv),
P64(v_start));
priv = v_start;
}
// just counts number of events
INLINE Counter omptarget_nvptx_CounterGroup::Next() {
Counter oldVal = atomicAdd(&v_event, (Counter)1);
PRINT(LD_SYNCD, "next event counter 0x%llx with val %lld->%lld\n",
P64(&v_event), P64(oldVal), P64(oldVal + 1));
return oldVal;
}
// set priv to n, to be used in later waitOrRelease
INLINE void omptarget_nvptx_CounterGroup::Complete(Counter &priv, Counter n) {
PRINT(LD_SYNCD, "complete priv counter 0x%llx with val %llu->%llu (+%llu)\n",
P64(&priv), P64(priv), P64(priv + n), n);
priv += n;
}
INLINE void omptarget_nvptx_CounterGroup::Release(Counter priv,
Counter current_event_value) {
if (priv - 1 == current_event_value) {
PRINT(LD_SYNCD, "Release start counter 0x%llx with val %lld->%lld\n",
P64(&v_start), P64(v_start), P64(priv));
v_start = priv;
}
}
// check priv and decide if we have to wait or can free the other warps
INLINE void
omptarget_nvptx_CounterGroup::WaitOrRelease(Counter priv,
Counter current_event_value) {
if (priv - 1 == current_event_value) {
PRINT(LD_SYNCD, "Release start counter 0x%llx with val %lld->%lld\n",
P64(&v_start), P64(v_start), P64(priv));
v_start = priv;
} else {
PRINT(LD_SYNCD,
"Start waiting while start counter 0x%llx with val %lld < %lld\n",
P64(&v_start), P64(v_start), P64(priv));
while (priv > v_start) {
// IDLE LOOP
// start is volatile: it will be re-loaded at each while loop
}
PRINT(LD_SYNCD,
"Done waiting as start counter 0x%llx with val %lld >= %lld\n",
P64(&v_start), P64(v_start), P64(priv));
}
}
+7 -10
View File
@@ -1,9 +1,8 @@
//===------ critical.cu - NVPTX OpenMP critical ------------------ CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -16,17 +15,15 @@
#include "omptarget-nvptx.h"
EXTERN
void __kmpc_critical(kmp_Indent *loc, int32_t global_tid,
void __kmpc_critical(kmp_Ident *loc, int32_t global_tid,
kmp_CriticalName *lck) {
PRINT0(LD_IO, "call to kmpc_critical()\n");
omptarget_nvptx_TeamDescr &teamDescr = getMyTeamDescriptor();
omp_set_lock(teamDescr.CriticalLock());
omp_set_lock((omp_lock_t *)lck);
}
EXTERN
void __kmpc_end_critical(kmp_Indent *loc, int32_t global_tid,
void __kmpc_end_critical(kmp_Ident *loc, int32_t global_tid,
kmp_CriticalName *lck) {
PRINT0(LD_IO, "call to kmpc_end_critical()\n");
omptarget_nvptx_TeamDescr &teamDescr = getMyTeamDescriptor();
omp_unset_lock(teamDescr.CriticalLock());
omp_unset_lock((omp_lock_t *)lck);
}
+171 -103
View File
@@ -1,9 +1,8 @@
//===----- data_sharing.cu - NVPTX OpenMP debug utilities -------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -11,44 +10,29 @@
//
//===----------------------------------------------------------------------===//
#include "omptarget-nvptx.h"
#include "target_impl.h"
#include <stdio.h>
// Number of threads in the CUDA block.
__device__ static unsigned getNumThreads() { return blockDim.x; }
// Thread ID in the CUDA block
__device__ static unsigned getThreadId() { return threadIdx.x; }
// Warp ID in the CUDA block
__device__ static unsigned getWarpId() { return threadIdx.x / WARPSIZE; }
INLINE static unsigned getWarpId() { return threadIdx.x / WARPSIZE; }
// Lane ID in the CUDA warp.
__device__ static unsigned getLaneId() { return threadIdx.x % WARPSIZE; }
// The CUDA thread ID of the master thread.
__device__ static unsigned getMasterThreadId() {
unsigned Mask = WARPSIZE - 1;
return (getNumThreads() - 1) & (~Mask);
}
// Find the active threads in the warp - return a mask whose n-th bit is set if
// the n-th thread in the warp is active.
__device__ static unsigned getActiveThreadsMask() {
return __BALLOT_SYNC(0xFFFFFFFF, true);
}
INLINE static unsigned getLaneId() { return threadIdx.x % WARPSIZE; }
// Return true if this is the first active thread in the warp.
__device__ static bool IsWarpMasterActiveThread() {
unsigned long long Mask = getActiveThreadsMask();
unsigned long long ShNum = WARPSIZE - (getThreadId() % WARPSIZE);
INLINE static bool IsWarpMasterActiveThread() {
unsigned long long Mask = __kmpc_impl_activemask();
unsigned long long ShNum = WARPSIZE - (GetThreadIdInBlock() % WARPSIZE);
unsigned long long Sh = Mask << ShNum;
// Truncate Sh to the 32 lower bits
return (unsigned)Sh == 0;
}
// Return true if this is the master thread.
__device__ static bool IsMasterThread() {
return !isSPMDMode() && getMasterThreadId() == getThreadId();
INLINE static bool IsMasterThread(bool isSPMDExecutionMode) {
return !isSPMDExecutionMode && GetMasterThreadID() == GetThreadIdInBlock();
}
/// Return the provided size aligned to the size of a pointer.
__device__ static size_t AlignVal(size_t Val) {
INLINE static size_t AlignVal(size_t Val) {
const size_t Align = (size_t)sizeof(void *);
if (Val & (Align - 1)) {
Val += Align;
@@ -79,38 +63,40 @@ __device__ static size_t AlignVal(size_t Val) {
EXTERN void
__kmpc_initialize_data_sharing_environment(__kmpc_data_sharing_slot *rootS,
size_t InitialDataSize) {
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Runtime must be initialized.");
DSPRINT0(DSFLAG_INIT,
"Entering __kmpc_initialize_data_sharing_environment\n");
unsigned WID = getWarpId();
DSPRINT(DSFLAG_INIT, "Warp ID: %d\n", WID);
DSPRINT(DSFLAG_INIT, "Warp ID: %u\n", WID);
omptarget_nvptx_TeamDescr *teamDescr =
&omptarget_nvptx_threadPrivateContext->TeamContext();
__kmpc_data_sharing_slot *RootS = teamDescr->RootS(WID, IsMasterThread());
__kmpc_data_sharing_slot *RootS =
teamDescr->RootS(WID, IsMasterThread(isSPMDMode()));
DataSharingState.SlotPtr[WID] = RootS;
DataSharingState.StackPtr[WID] = (void *)&RootS->Data[0];
// We don't need to initialize the frame and active threads.
DSPRINT(DSFLAG_INIT, "Initial data size: %08x \n", InitialDataSize);
DSPRINT(DSFLAG_INIT, "Root slot at: %016llx \n", (long long)RootS);
DSPRINT(DSFLAG_INIT, "Initial data size: %08x \n", (unsigned)InitialDataSize);
DSPRINT(DSFLAG_INIT, "Root slot at: %016llx \n", (unsigned long long)RootS);
DSPRINT(DSFLAG_INIT, "Root slot data-end at: %016llx \n",
(long long)RootS->DataEnd);
DSPRINT(DSFLAG_INIT, "Root slot next at: %016llx \n", (long long)RootS->Next);
(unsigned long long)RootS->DataEnd);
DSPRINT(DSFLAG_INIT, "Root slot next at: %016llx \n",
(unsigned long long)RootS->Next);
DSPRINT(DSFLAG_INIT, "Shared slot ptr at: %016llx \n",
(long long)DataSharingState.SlotPtr[WID]);
(unsigned long long)DataSharingState.SlotPtr[WID]);
DSPRINT(DSFLAG_INIT, "Shared stack ptr at: %016llx \n",
(long long)DataSharingState.StackPtr[WID]);
(unsigned long long)DataSharingState.StackPtr[WID]);
DSPRINT0(DSFLAG_INIT, "Exiting __kmpc_initialize_data_sharing_environment\n");
}
EXTERN void *__kmpc_data_sharing_environment_begin(
__kmpc_data_sharing_slot **SavedSharedSlot, void **SavedSharedStack,
void **SavedSharedFrame, int32_t *SavedActiveThreads,
void **SavedSharedFrame, __kmpc_impl_lanemask_t *SavedActiveThreads,
size_t SharingDataSize, size_t SharingDefaultDataSize,
int16_t IsOMPRuntimeInitialized) {
@@ -121,16 +107,17 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
if (!IsOMPRuntimeInitialized)
return (void *)&DataSharingState;
DSPRINT(DSFLAG, "Data Size %016llx\n", SharingDataSize);
DSPRINT(DSFLAG, "Default Data Size %016llx\n", SharingDefaultDataSize);
DSPRINT(DSFLAG, "Data Size %016llx\n", (unsigned long long)SharingDataSize);
DSPRINT(DSFLAG, "Default Data Size %016llx\n",
(unsigned long long)SharingDefaultDataSize);
unsigned WID = getWarpId();
unsigned CurActiveThreads = getActiveThreadsMask();
__kmpc_impl_lanemask_t CurActiveThreads = __kmpc_impl_activemask();
__kmpc_data_sharing_slot *&SlotP = DataSharingState.SlotPtr[WID];
void *&StackP = DataSharingState.StackPtr[WID];
void *&FrameP = DataSharingState.FramePtr[WID];
int32_t &ActiveT = DataSharingState.ActiveThreads[WID];
void * volatile &FrameP = DataSharingState.FramePtr[WID];
__kmpc_impl_lanemask_t &ActiveT = DataSharingState.ActiveThreads[WID];
DSPRINT0(DSFLAG, "Save current slot/stack values.\n");
// Save the current values.
@@ -139,11 +126,11 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
*SavedSharedFrame = FrameP;
*SavedActiveThreads = ActiveT;
DSPRINT(DSFLAG, "Warp ID: %d\n", WID);
DSPRINT(DSFLAG, "Saved slot ptr at: %016llx \n", (long long)SlotP);
DSPRINT(DSFLAG, "Saved stack ptr at: %016llx \n", (long long)StackP);
DSPRINT(DSFLAG, "Warp ID: %u\n", WID);
DSPRINT(DSFLAG, "Saved slot ptr at: %016llx \n", (unsigned long long)SlotP);
DSPRINT(DSFLAG, "Saved stack ptr at: %016llx \n", (unsigned long long)StackP);
DSPRINT(DSFLAG, "Saved frame ptr at: %016llx \n", (long long)FrameP);
DSPRINT(DSFLAG, "Active threads: %08x \n", ActiveT);
DSPRINT(DSFLAG, "Active threads: %08x \n", (unsigned)ActiveT);
// Only the warp active master needs to grow the stack.
if (IsWarpMasterActiveThread()) {
@@ -161,12 +148,16 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
const uintptr_t RequiredEndAddress =
CurrentStartAddress + (uintptr_t)SharingDataSize;
DSPRINT(DSFLAG, "Data Size %016llx\n", SharingDataSize);
DSPRINT(DSFLAG, "Default Data Size %016llx\n", SharingDefaultDataSize);
DSPRINT(DSFLAG, "Current Start Address %016llx\n", CurrentStartAddress);
DSPRINT(DSFLAG, "Current End Address %016llx\n", CurrentEndAddress);
DSPRINT(DSFLAG, "Required End Address %016llx\n", RequiredEndAddress);
DSPRINT(DSFLAG, "Active Threads %08x\n", ActiveT);
DSPRINT(DSFLAG, "Data Size %016llx\n", (unsigned long long)SharingDataSize);
DSPRINT(DSFLAG, "Default Data Size %016llx\n",
(unsigned long long)SharingDefaultDataSize);
DSPRINT(DSFLAG, "Current Start Address %016llx\n",
(unsigned long long)CurrentStartAddress);
DSPRINT(DSFLAG, "Current End Address %016llx\n",
(unsigned long long)CurrentEndAddress);
DSPRINT(DSFLAG, "Required End Address %016llx\n",
(unsigned long long)RequiredEndAddress);
DSPRINT(DSFLAG, "Active Threads %08x\n", (unsigned)ActiveT);
// If we require a new slot, allocate it and initialize it (or attempt to
// reuse one). Also, set the shared stack and slot pointers to the new
@@ -184,11 +175,11 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
(uintptr_t)(&ExistingSlot->Data[0]);
if (ExistingSlotSize >= NewSize) {
DSPRINT(DSFLAG, "Reusing stack slot %016llx\n",
(long long)ExistingSlot);
(unsigned long long)ExistingSlot);
NewSlot = ExistingSlot;
} else {
DSPRINT(DSFLAG, "Cleaning up -failed reuse - %016llx\n",
(long long)SlotP->Next);
(unsigned long long)SlotP->Next);
free(ExistingSlot);
}
}
@@ -197,7 +188,7 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
NewSlot = (__kmpc_data_sharing_slot *)malloc(
sizeof(__kmpc_data_sharing_slot) + NewSize);
DSPRINT(DSFLAG, "New slot allocated %016llx (data size=%016llx)\n",
(long long)NewSlot, NewSize);
(unsigned long long)NewSlot, NewSize);
}
NewSlot->Next = 0;
@@ -213,7 +204,7 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
// not eliminate them because that may be used to return data.
if (SlotP->Next) {
DSPRINT(DSFLAG, "Cleaning up - old not required - %016llx\n",
(long long)SlotP->Next);
(unsigned long long)SlotP->Next);
free(SlotP->Next);
SlotP->Next = 0;
}
@@ -234,7 +225,7 @@ EXTERN void *__kmpc_data_sharing_environment_begin(
EXTERN void __kmpc_data_sharing_environment_end(
__kmpc_data_sharing_slot **SavedSharedSlot, void **SavedSharedStack,
void **SavedSharedFrame, int32_t *SavedActiveThreads,
void **SavedSharedFrame, __kmpc_impl_lanemask_t *SavedActiveThreads,
int32_t IsEntryPoint) {
DSPRINT0(DSFLAG, "Entering __kmpc_data_sharing_environment_end\n");
@@ -247,8 +238,9 @@ EXTERN void __kmpc_data_sharing_environment_end(
// The master thread cleans the saved slot, because this is an environment
// only for the master.
__kmpc_data_sharing_slot *S =
IsMasterThread() ? *SavedSharedSlot : DataSharingState.SlotPtr[WID];
__kmpc_data_sharing_slot *S = IsMasterThread(isSPMDMode())
? *SavedSharedSlot
: DataSharingState.SlotPtr[WID];
if (S->Next) {
free(S->Next);
@@ -260,7 +252,7 @@ EXTERN void __kmpc_data_sharing_environment_end(
return;
}
int32_t CurActive = getActiveThreadsMask();
__kmpc_impl_lanemask_t CurActive = __kmpc_impl_activemask();
// Only the warp master can restore the stack and frame information, and only
// if there are no other threads left behind in this environment (i.e. the
@@ -268,32 +260,35 @@ EXTERN void __kmpc_data_sharing_environment_end(
// assume that threads will converge right after the call site that started
// the environment.
if (IsWarpMasterActiveThread()) {
int32_t &ActiveT = DataSharingState.ActiveThreads[WID];
__kmpc_impl_lanemask_t &ActiveT = DataSharingState.ActiveThreads[WID];
DSPRINT0(DSFLAG, "Before restoring the stack\n");
// Zero the bits in the mask. If it is still different from zero, then we
// have other threads that will return after the current ones.
ActiveT &= ~CurActive;
DSPRINT(DSFLAG, "Active threads: %08x; New mask: %08x\n", CurActive,
ActiveT);
DSPRINT(DSFLAG, "Active threads: %08x; New mask: %08x\n",
(unsigned)CurActive, (unsigned)ActiveT);
if (!ActiveT) {
// No other active threads? Great, lets restore the stack.
__kmpc_data_sharing_slot *&SlotP = DataSharingState.SlotPtr[WID];
void *&StackP = DataSharingState.StackPtr[WID];
void *&FrameP = DataSharingState.FramePtr[WID];
void * volatile &FrameP = DataSharingState.FramePtr[WID];
SlotP = *SavedSharedSlot;
StackP = *SavedSharedStack;
FrameP = *SavedSharedFrame;
ActiveT = *SavedActiveThreads;
DSPRINT(DSFLAG, "Restored slot ptr at: %016llx \n", (long long)SlotP);
DSPRINT(DSFLAG, "Restored stack ptr at: %016llx \n", (long long)StackP);
DSPRINT(DSFLAG, "Restored frame ptr at: %016llx \n", (long long)FrameP);
DSPRINT(DSFLAG, "Active threads: %08x \n", ActiveT);
DSPRINT(DSFLAG, "Restored slot ptr at: %016llx \n",
(unsigned long long)SlotP);
DSPRINT(DSFLAG, "Restored stack ptr at: %016llx \n",
(unsigned long long)StackP);
DSPRINT(DSFLAG, "Restored frame ptr at: %016llx \n",
(unsigned long long)FrameP);
DSPRINT(DSFLAG, "Active threads: %08x \n", (unsigned)ActiveT);
}
}
@@ -319,9 +314,9 @@ __kmpc_get_data_sharing_environment_frame(int32_t SourceThreadID,
unsigned SourceWID = SourceThreadID / WARPSIZE;
DSPRINT(DSFLAG, "Source warp: %d\n", SourceWID);
DSPRINT(DSFLAG, "Source warp: %u\n", SourceWID);
void *P = DataSharingState.FramePtr[SourceWID];
void * volatile P = DataSharingState.FramePtr[SourceWID];
DSPRINT0(DSFLAG, "Exiting __kmpc_get_data_sharing_environment_frame\n");
return P;
}
@@ -330,7 +325,8 @@ __kmpc_get_data_sharing_environment_frame(int32_t SourceThreadID,
// Runtime functions for trunk data sharing scheme.
////////////////////////////////////////////////////////////////////////////////
INLINE void data_sharing_init_stack_common() {
INLINE static void data_sharing_init_stack_common() {
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Runtime must be initialized.");
omptarget_nvptx_TeamDescr *teamDescr =
&omptarget_nvptx_threadPrivateContext->TeamContext();
@@ -346,6 +342,7 @@ INLINE void data_sharing_init_stack_common() {
// initialization). This function is called only by the MASTER thread of each
// team in non-SPMD mode.
EXTERN void __kmpc_data_sharing_init_stack() {
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Runtime must be initialized.");
// This function initializes the stack pointer with the pointer to the
// statically allocated shared memory slots. The size of a shared memory
// slot is pre-determined to be 256 bytes.
@@ -357,6 +354,7 @@ EXTERN void __kmpc_data_sharing_init_stack() {
// once at the beginning of a data sharing context (coincides with the kernel
// initialization). This function is called in SPMD mode only.
EXTERN void __kmpc_data_sharing_init_stack_spmd() {
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Runtime must be initialized.");
// This function initializes the stack pointer with the pointer to the
// statically allocated shared memory slots. The size of a shared memory
// slot is pre-determined to be 256 bytes.
@@ -366,34 +364,28 @@ EXTERN void __kmpc_data_sharing_init_stack_spmd() {
__threadfence_block();
}
// Called at the time of the kernel initialization. This is used to initilize
// the list of references to shared variables and to pre-allocate global storage
// for holding the globalized variables.
//
// By default the globalized variables are stored in global memory. If the
// UseSharedMemory is set to true, the runtime will attempt to use shared memory
// as long as the size requested fits the pre-allocated size.
EXTERN void* __kmpc_data_sharing_push_stack(size_t DataSize,
int16_t UseSharedMemory) {
// Frame pointer must be visible to all workers in the same warp.
unsigned WID = getWarpId();
void *&FrameP = DataSharingState.FramePtr[WID];
INLINE static void* data_sharing_push_stack_common(size_t PushSize) {
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Expected initialized runtime.");
// Only warp active master threads manage the stack.
if (IsWarpMasterActiveThread()) {
bool IsWarpMaster = (GetThreadIdInBlock() % WARPSIZE) == 0;
// Add worst-case padding to DataSize so that future stack allocations are
// correctly aligned.
const size_t Alignment = 8;
PushSize = (PushSize + (Alignment - 1)) / Alignment * Alignment;
// Frame pointer must be visible to all workers in the same warp.
const unsigned WID = getWarpId();
void *FrameP = 0;
__kmpc_impl_lanemask_t CurActive = __kmpc_impl_activemask();
if (IsWarpMaster) {
// SlotP will point to either the shared memory slot or an existing
// global memory slot.
__kmpc_data_sharing_slot *&SlotP = DataSharingState.SlotPtr[WID];
void *&StackP = DataSharingState.StackPtr[WID];
// Compute the total memory footprint of the requested data.
// The master thread requires a stack only for itself. A worker
// thread (which at this point is a warp master) will require
// space for the variables of each thread in the warp,
// i.e. one DataSize chunk per warp lane.
// TODO: change WARPSIZE to the number of active threads in the warp.
size_t PushSize = IsMasterThread() ? DataSize : WARPSIZE * DataSize;
// Check if we have room for the data in the current slot.
const uintptr_t StartAddress = (uintptr_t)StackP;
const uintptr_t EndAddress = (uintptr_t)SlotP->DataEnd;
@@ -429,20 +421,51 @@ EXTERN void* __kmpc_data_sharing_push_stack(size_t DataSize,
// The stack pointer always points to the next free stack frame.
StackP = &NewSlot->Data[0] + PushSize;
// The frame pointer always points to the beginning of the frame.
FrameP = &NewSlot->Data[0];
FrameP = DataSharingState.FramePtr[WID] = &NewSlot->Data[0];
} else {
// Add the data chunk to the current slot. The frame pointer is set to
// point to the start of the new frame held in StackP.
FrameP = StackP;
FrameP = DataSharingState.FramePtr[WID] = StackP;
// Reset stack pointer to the requested address.
StackP = (void *)RequestedEndAddress;
}
}
// Get address from lane 0.
int *FP = (int *)&FrameP;
FP[0] = __kmpc_impl_shfl_sync(CurActive, FP[0], 0);
if (sizeof(FrameP) == 8)
FP[1] = __kmpc_impl_shfl_sync(CurActive, FP[1], 0);
__threadfence_block();
return FrameP;
}
EXTERN void *__kmpc_data_sharing_coalesced_push_stack(size_t DataSize,
int16_t UseSharedMemory) {
return data_sharing_push_stack_common(DataSize);
}
// Called at the time of the kernel initialization. This is used to initilize
// the list of references to shared variables and to pre-allocate global storage
// for holding the globalized variables.
//
// By default the globalized variables are stored in global memory. If the
// UseSharedMemory is set to true, the runtime will attempt to use shared memory
// as long as the size requested fits the pre-allocated size.
EXTERN void *__kmpc_data_sharing_push_stack(size_t DataSize,
int16_t UseSharedMemory) {
// Compute the total memory footprint of the requested data.
// The master thread requires a stack only for itself. A worker
// thread (which at this point is a warp master) will require
// space for the variables of each thread in the warp,
// i.e. one DataSize chunk per warp lane.
// TODO: change WARPSIZE to the number of active threads in the warp.
size_t PushSize = (isRuntimeUninitialized() || IsMasterThread(isSPMDMode()))
? DataSize
: WARPSIZE * DataSize;
// Compute the start address of the frame of each thread in the warp.
uintptr_t FrameStartAddress = (uintptr_t)FrameP;
uintptr_t FrameStartAddress =
(uintptr_t) data_sharing_push_stack_common(PushSize);
FrameStartAddress += (uintptr_t) (getLaneId() * DataSize);
return (void *)FrameStartAddress;
}
@@ -453,7 +476,11 @@ EXTERN void* __kmpc_data_sharing_push_stack(size_t DataSize,
// reclaim all outstanding global memory slots since it is
// likely we have reached the end of the kernel.
EXTERN void __kmpc_data_sharing_pop_stack(void *FrameStart) {
if (IsWarpMasterActiveThread()) {
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Expected initialized runtime.");
__threadfence_block();
if (GetThreadIdInBlock() % WARPSIZE == 0) {
unsigned WID = getWarpId();
// Current slot
@@ -462,13 +489,13 @@ EXTERN void __kmpc_data_sharing_pop_stack(void *FrameStart) {
// Pointer to next available stack.
void *&StackP = DataSharingState.StackPtr[WID];
// Pop the frame.
StackP = FrameStart;
// If the current slot is empty, we need to free the slot after the
// pop.
bool SlotEmpty = (StackP == &SlotP->Data[0]);
// Pop the frame.
StackP = FrameStart;
if (SlotEmpty && SlotP->Prev) {
// Before removing the slot we need to reset StackP.
StackP = SlotP->PrevSlotStackPtr;
@@ -479,8 +506,6 @@ EXTERN void __kmpc_data_sharing_pop_stack(void *FrameStart) {
SlotP->Next = 0;
}
}
__threadfence_block();
}
// Begin a data sharing context. Maintain a list of references to shared
@@ -511,3 +536,46 @@ EXTERN void __kmpc_end_sharing_variables() {
EXTERN void __kmpc_get_shared_variables(void ***GlobalArgs) {
*GlobalArgs = omptarget_nvptx_globalArgs.GetArgs();
}
// This function is used to init static memory manager. This manager is used to
// manage statically allocated global memory. This memory is allocated by the
// compiler and used to correctly implement globalization of the variables in
// target, teams and distribute regions.
EXTERN void __kmpc_get_team_static_memory(int16_t isSPMDExecutionMode,
const void *buf, size_t size,
int16_t is_shared,
const void **frame) {
if (is_shared) {
*frame = buf;
return;
}
if (isSPMDExecutionMode) {
if (GetThreadIdInBlock() == 0) {
*frame = omptarget_nvptx_simpleMemoryManager.Acquire(buf, size);
}
__kmpc_impl_syncthreads();
return;
}
ASSERT0(LT_FUSSY, GetThreadIdInBlock() == GetMasterThreadID(),
"Must be called only in the target master thread.");
*frame = omptarget_nvptx_simpleMemoryManager.Acquire(buf, size);
__threadfence();
}
EXTERN void __kmpc_restore_team_static_memory(int16_t isSPMDExecutionMode,
int16_t is_shared) {
if (is_shared)
return;
if (isSPMDExecutionMode) {
__kmpc_impl_syncthreads();
if (GetThreadIdInBlock() == 0) {
omptarget_nvptx_simpleMemoryManager.Release();
}
return;
}
__threadfence();
ASSERT0(LT_FUSSY, GetThreadIdInBlock() == GetMasterThreadID(),
"Must be called only in the target master thread.");
omptarget_nvptx_simpleMemoryManager.Release();
}
+34 -22
View File
@@ -1,9 +1,8 @@
//===------------- debug.h - NVPTX OpenMP debug macros ----------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -127,9 +126,29 @@
#if OMPTARGET_NVPTX_DEBUG || OMPTARGET_NVPTX_TEST || OMPTARGET_NVPTX_WARNING
#include <stdio.h>
#include "option.h"
template <typename... Arguments>
NOINLINE static void log(const char *fmt, Arguments... parameters) {
printf(fmt, (int)blockIdx.x, (int)threadIdx.x, (int)(threadIdx.x / WARPSIZE),
(int)(threadIdx.x & 0x1F), parameters...);
}
#endif
#if OMPTARGET_NVPTX_TEST
#include <assert.h>
template <typename... Arguments>
NOINLINE static void check(bool cond, const char *fmt,
Arguments... parameters) {
if (!cond)
printf(fmt, (int)blockIdx.x, (int)threadIdx.x,
(int)(threadIdx.x / WARPSIZE), (int)(threadIdx.x & 0x1F),
parameters...);
assert(cond);
}
NOINLINE static void check(bool cond) { assert(cond); }
#endif
// set flags that are tested (inclusion properties)
@@ -164,16 +183,14 @@
#define PRINT0(_flag, _str) \
{ \
if (omptarget_device_environment.debug_level && DON(_flag)) { \
printf("<b %2d, t %4d, w %2d, l %2d>: " _str, blockIdx.x, threadIdx.x, \
threadIdx.x / WARPSIZE, threadIdx.x & 0x1F); \
log("<b %2d, t %4d, w %2d, l %2d>: " _str); \
} \
}
#define PRINT(_flag, _str, _args...) \
{ \
if (omptarget_device_environment.debug_level && DON(_flag)) { \
printf("<b %2d, t %4d, w %2d, l %2d>: " _str, blockIdx.x, threadIdx.x, \
threadIdx.x / WARPSIZE, threadIdx.x & 0x1F, _args); \
log("<b %2d, t %4d, w %2d, l %2d>: " _str, _args); \
} \
}
#else
@@ -201,13 +218,13 @@
#define ASSERT0(_flag, _cond, _str) \
{ \
if (TON(_flag)) { \
assert(_cond); \
check(_cond); \
} \
}
#define ASSERT(_flag, _cond, _str, _args...) \
{ \
if (TON(_flag)) { \
assert(_cond); \
check(_cond); \
} \
}
@@ -216,18 +233,15 @@
#define TON(_flag) ((OMPTARGET_NVPTX_TEST) & (_flag))
#define ASSERT0(_flag, _cond, _str) \
{ \
if (TON(_flag) && !(_cond)) { \
printf("<b %3d, t %4d, w %2d, l %2d> ASSERT: " _str "\n", blockIdx.x, \
threadIdx.x, threadIdx.x / WARPSIZE, threadIdx.x & 0x1F); \
assert(_cond); \
if (TON(_flag)) { \
check((_cond), "<b %3d, t %4d, w %2d, l %2d> ASSERT: " _str "\n"); \
} \
}
#define ASSERT(_flag, _cond, _str, _args...) \
{ \
if (TON(_flag) && !(_cond)) { \
printf("<b %3d, t %4d, w %2d, l %d2> ASSERT: " _str "\n", blockIdx.x, \
threadIdx.x, threadIdx.x / WARPSIZE, threadIdx.x & 0x1F, _args); \
assert(_cond); \
if (TON(_flag)) { \
check((_cond), "<b %3d, t %4d, w %2d, l %d2> ASSERT: " _str "\n", \
_args); \
} \
}
@@ -253,15 +267,13 @@
#define WARNING0(_flag, _str) \
{ \
if (WON(_flag)) { \
printf("<b %2d, t %4d, w %2d, l %2d> WARNING: " _str, blockIdx.x, \
threadIdx.x, threadIdx.x / WARPSIZE, threadIdx.x & 0x1F); \
log("<b %2d, t %4d, w %2d, l %2d> WARNING: " _str); \
} \
}
#define WARNING(_flag, _str, _args...) \
{ \
if (WON(_flag)) { \
printf("<b %2d, t %4d, w %2d, l %2d> WARNING: " _str, blockIdx.x, \
threadIdx.x, threadIdx.x / WARPSIZE, threadIdx.x & 0x1F, _args); \
log("<b %2d, t %4d, w %2d, l %2d> WARNING: " _str, _args); \
} \
}
+84 -106
View File
@@ -1,9 +1,8 @@
//===------------ libcall.cu - NVPTX OpenMP user calls ----------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -31,61 +30,61 @@ EXTERN double omp_get_wtime(void) {
}
EXTERN void omp_set_num_threads(int num) {
// Ignore it for SPMD mode.
if (isSPMDMode())
return;
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Expected initialized runtime.");
PRINT(LD_IO, "call omp_set_num_threads(num %d)\n", num);
if (num <= 0) {
WARNING0(LW_INPUT, "expected positive num; ignore\n");
} else {
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
currTaskDescr->NThreads() = num;
} else if (parallelLevel[GetWarpId()] == 0) {
nThreads = num;
}
}
EXTERN int omp_get_num_threads(void) {
int tid = GetLogicalThreadIdInBlock();
int rc = GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized());
int rc = GetNumberOfOmpThreads(isSPMDMode());
PRINT(LD_IO, "call omp_get_num_threads() return %d\n", rc);
return rc;
}
EXTERN int omp_get_max_threads(void) {
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
int rc = 1; // default is 1 thread avail
if (!currTaskDescr->InParallelRegion()) {
// not currently in a parallel region... all are available
rc = GetNumberOfProcsInTeam();
ASSERT0(LT_FUSSY, rc >= 0, "bad number of threads");
}
if (parallelLevel[GetWarpId()] > 0)
// We're already in parallel region.
return 1; // default is 1 thread avail
// Not currently in a parallel region, return what was set.
int rc = 1;
if (parallelLevel[GetWarpId()] == 0)
rc = nThreads;
ASSERT0(LT_FUSSY, rc >= 0, "bad number of threads");
PRINT(LD_IO, "call omp_get_max_threads() return %d\n", rc);
return rc;
}
EXTERN int omp_get_thread_limit(void) {
// per contention group.. meaning threads in current team
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
int rc = currTaskDescr->ThreadLimit();
if (isSPMDMode())
return GetNumberOfThreadsInBlock();
int rc = threadLimit;
PRINT(LD_IO, "call omp_get_thread_limit() return %d\n", rc);
return rc;
}
EXTERN int omp_get_thread_num() {
int tid = GetLogicalThreadIdInBlock();
int rc = GetOmpThreadId(tid, isSPMDMode(), isRuntimeUninitialized());
bool isSPMDExecutionMode = isSPMDMode();
int tid = GetLogicalThreadIdInBlock(isSPMDExecutionMode);
int rc = GetOmpThreadId(tid, isSPMDExecutionMode);
PRINT(LD_IO, "call omp_get_thread_num() returns %d\n", rc);
return rc;
}
EXTERN int omp_get_num_procs(void) {
int rc = GetNumberOfProcsInDevice();
int rc = GetNumberOfProcsInDevice(isSPMDMode());
PRINT(LD_IO, "call omp_get_num_procs() returns %d\n", rc);
return rc;
}
EXTERN int omp_in_parallel(void) {
int rc = 0;
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
if (currTaskDescr->InParallelRegion()) {
rc = 1;
}
int rc = parallelLevel[GetWarpId()] > OMP_ACTIVE_PARALLEL_LEVEL ? 1 : 0;
PRINT(LD_IO, "call omp_in_parallel() returns %d\n", rc);
return rc;
}
@@ -101,22 +100,11 @@ EXTERN int omp_in_final(void) {
}
EXTERN void omp_set_dynamic(int flag) {
PRINT(LD_IO, "call omp_set_dynamic(%d)\n", flag);
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
if (flag) {
currTaskDescr->SetDynamic();
} else {
currTaskDescr->ClearDynamic();
}
PRINT(LD_IO, "call omp_set_dynamic(%d) is ignored (no support)\n", flag);
}
EXTERN int omp_get_dynamic(void) {
int rc = 0;
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
if (currTaskDescr->IsDynamic()) {
rc = 1;
}
PRINT(LD_IO, "call omp_get_dynamic() returns %d\n", rc);
return rc;
}
@@ -145,43 +133,28 @@ EXTERN int omp_get_max_active_levels(void) {
}
EXTERN int omp_get_level(void) {
int level = 0;
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
ASSERT0(LT_FUSSY, currTaskDescr,
"do not expect fct to be called in a non-active thread");
do {
if (currTaskDescr->IsParallelConstruct()) {
level++;
}
currTaskDescr = currTaskDescr->GetPrevTaskDescr();
} while (currTaskDescr);
int level = parallelLevel[GetWarpId()] & (OMP_ACTIVE_PARALLEL_LEVEL - 1);
PRINT(LD_IO, "call omp_get_level() returns %d\n", level);
return level;
}
EXTERN int omp_get_active_level(void) {
int level = 0; // no active level parallelism
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
ASSERT0(LT_FUSSY, currTaskDescr,
"do not expect fct to be called in a non-active thread");
do {
if (currTaskDescr->ThreadsInTeam() > 1) {
// has a parallel with more than one thread in team
level = 1;
break;
}
currTaskDescr = currTaskDescr->GetPrevTaskDescr();
} while (currTaskDescr);
int level = parallelLevel[GetWarpId()] > OMP_ACTIVE_PARALLEL_LEVEL ? 1 : 0;
PRINT(LD_IO, "call omp_get_active_level() returns %d\n", level)
return level;
}
EXTERN int omp_get_ancestor_thread_num(int level) {
int rc = 0; // default at level 0
if (level >= 0) {
if (isSPMDMode())
return level == 1 ? GetThreadIdInBlock() : 0;
int rc = -1;
// If level is 0 or all parallel regions are not active - return 0.
unsigned parLevel = parallelLevel[GetWarpId()];
if (level == 1 && parLevel > OMP_ACTIVE_PARALLEL_LEVEL) {
int totLevel = omp_get_level();
if (level <= totLevel) {
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
omptarget_nvptx_TaskDescr *currTaskDescr =
getMyTopTaskDescriptor(/*isSPMDExecutionMode=*/false);
int steps = totLevel - level;
PRINT(LD_IO, "backtrack %d steps\n", steps);
ASSERT0(LT_FUSSY, currTaskDescr,
@@ -191,14 +164,14 @@ EXTERN int omp_get_ancestor_thread_num(int level) {
// print current state
omp_sched_t sched = currTaskDescr->GetRuntimeSched();
PRINT(LD_ALL,
"task descr %s %d: %s, in par %d, dyn %d, rt sched %d,"
"task descr %s %d: %s, in par %d, rt sched %d,"
" chunk %" PRIu64 "; tid %d, tnum %d, nthreads %d\n",
"ancestor", steps,
(currTaskDescr->IsParallelConstruct() ? "par" : "task"),
currTaskDescr->InParallelRegion(), currTaskDescr->IsDynamic(),
sched, currTaskDescr->RuntimeChunkSize(),
currTaskDescr->ThreadId(), currTaskDescr->ThreadsInTeam(),
currTaskDescr->NThreads());
(int)currTaskDescr->InParallelRegion(), (int)sched,
currTaskDescr->RuntimeChunkSize(),
(int)currTaskDescr->ThreadId(), (int)threadsInTeam,
(int)nThreads);
}
if (currTaskDescr->IsParallelConstruct()) {
@@ -213,6 +186,12 @@ EXTERN int omp_get_ancestor_thread_num(int level) {
} while (currTaskDescr);
ASSERT0(LT_FUSSY, !steps, "expected to find all steps");
}
} else if (level == 0 ||
(level > 0 && parLevel < OMP_ACTIVE_PARALLEL_LEVEL &&
level <= parLevel) ||
(level > 1 && parLevel > OMP_ACTIVE_PARALLEL_LEVEL &&
level <= (parLevel - OMP_ACTIVE_PARALLEL_LEVEL))) {
rc = 0;
}
PRINT(LD_IO, "call omp_get_ancestor_thread_num(level %d) returns %d\n", level,
rc)
@@ -220,36 +199,36 @@ EXTERN int omp_get_ancestor_thread_num(int level) {
}
EXTERN int omp_get_team_size(int level) {
int rc = 1; // default at level 0
if (level >= 0) {
int totLevel = omp_get_level();
if (level <= totLevel) {
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
int steps = totLevel - level;
ASSERT0(LT_FUSSY, currTaskDescr,
"do not expect fct to be called in a non-active thread");
do {
if (currTaskDescr->IsParallelConstruct()) {
if (!steps) {
// found the level
rc = currTaskDescr->ThreadsInTeam();
break;
}
steps--;
}
currTaskDescr = currTaskDescr->GetPrevTaskDescr();
} while (currTaskDescr);
ASSERT0(LT_FUSSY, !steps, "expected to find all steps");
}
if (isSPMDMode())
return level == 1 ? GetNumberOfThreadsInBlock() : 1;
int rc = -1;
unsigned parLevel = parallelLevel[GetWarpId()];
// If level is 0 or all parallel regions are not active - return 1.
if (level == 1 && parLevel > OMP_ACTIVE_PARALLEL_LEVEL) {
rc = threadsInTeam;
} else if (level == 0 ||
(level > 0 && parLevel < OMP_ACTIVE_PARALLEL_LEVEL &&
level <= parLevel) ||
(level > 1 && parLevel > OMP_ACTIVE_PARALLEL_LEVEL &&
level <= (parLevel - OMP_ACTIVE_PARALLEL_LEVEL))) {
rc = 1;
}
PRINT(LD_IO, "call omp_get_team_size(level %d) returns %d\n", level, rc)
return rc;
}
EXTERN void omp_get_schedule(omp_sched_t *kind, int *modifier) {
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
*kind = currTaskDescr->GetRuntimeSched();
*modifier = currTaskDescr->RuntimeChunkSize();
if (isRuntimeUninitialized()) {
ASSERT0(LT_FUSSY, isSPMDMode(),
"Expected SPMD mode only with uninitialized runtime.");
*kind = omp_sched_static;
*modifier = 1;
} else {
omptarget_nvptx_TaskDescr *currTaskDescr =
getMyTopTaskDescriptor(isSPMDMode());
*kind = currTaskDescr->GetRuntimeSched();
*modifier = currTaskDescr->RuntimeChunkSize();
}
PRINT(LD_IO, "call omp_get_schedule returns sched %d and modif %d\n",
(int)*kind, *modifier);
}
@@ -257,8 +236,14 @@ EXTERN void omp_get_schedule(omp_sched_t *kind, int *modifier) {
EXTERN void omp_set_schedule(omp_sched_t kind, int modifier) {
PRINT(LD_IO, "call omp_set_schedule(sched %d, modif %d)\n", (int)kind,
modifier);
if (isRuntimeUninitialized()) {
ASSERT0(LT_FUSSY, isSPMDMode(),
"Expected SPMD mode only with uninitialized runtime.");
return;
}
if (kind >= omp_sched_static && kind < omp_sched_auto) {
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor();
omptarget_nvptx_TaskDescr *currTaskDescr =
getMyTopTaskDescriptor(isSPMDMode());
currTaskDescr->SetRuntimeSched(kind);
currTaskDescr->RuntimeChunkSize() = modifier;
PRINT(LD_IOD, "omp_set_schedule did set sched %d & modif %" PRIu64 "\n",
@@ -359,23 +344,21 @@ EXTERN int omp_get_max_task_priority(void) {
#define SET 1
EXTERN void omp_init_lock(omp_lock_t *lock) {
*lock = UNSET;
omp_unset_lock(lock);
PRINT0(LD_IO, "call omp_init_lock()\n");
}
EXTERN void omp_destroy_lock(omp_lock_t *lock) {
omp_unset_lock(lock);
PRINT0(LD_IO, "call omp_destroy_lock()\n");
}
EXTERN void omp_set_lock(omp_lock_t *lock) {
// int atomicCAS(int* address, int compare, int val);
// (old == compare ? val : old)
int compare = UNSET;
int val = SET;
// TODO: not sure spinning is a good idea here..
while (atomicCAS(lock, compare, val) != UNSET) {
while (atomicCAS(lock, UNSET, SET) != UNSET) {
clock_t start = clock();
clock_t now;
for (;;) {
@@ -391,9 +374,7 @@ EXTERN void omp_set_lock(omp_lock_t *lock) {
}
EXTERN void omp_unset_lock(omp_lock_t *lock) {
int compare = SET;
int val = UNSET;
int old = atomicCAS(lock, compare, val);
(void)atomicExch(lock, UNSET);
PRINT0(LD_IO, "call omp_unset_lock()\n");
}
@@ -401,10 +382,7 @@ EXTERN void omp_unset_lock(omp_lock_t *lock) {
EXTERN int omp_test_lock(omp_lock_t *lock) {
// int atomicCAS(int* address, int compare, int val);
// (old == compare ? val : old)
int compare = UNSET;
int val = SET;
int ret = atomicCAS(lock, compare, val);
int ret = atomicAdd(lock, 0);
PRINT(LD_IO, "call omp_test_lock() return %d\n", ret);
+246 -208
View File
@@ -1,9 +1,8 @@
//===------------ loop.cu - NVPTX OpenMP loop constructs --------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -14,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "omptarget-nvptx.h"
#include "target_impl.h"
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -93,105 +93,89 @@ public:
////////////////////////////////////////////////////////////////////////////////
// Support for Static Init
INLINE static void for_static_init(int32_t schedtype, int32_t *plastiter,
T *plower, T *pupper, ST *pstride,
ST chunk, bool IsSPMDExecutionMode,
bool IsRuntimeUninitialized) {
INLINE static void for_static_init(int32_t gtid, int32_t schedtype,
int32_t *plastiter, T *plower, T *pupper,
ST *pstride, ST chunk,
bool IsSPMDExecutionMode) {
// When IsRuntimeUninitialized is true, we assume that the caller is
// in an L0 parallel region and that all worker threads participate.
int tid = GetLogicalThreadIdInBlock();
// Assume we are in teams region or that we use a single block
// per target region
ST numberOfActiveOMPThreads = GetNumberOfOmpThreads(
tid, IsSPMDExecutionMode, IsRuntimeUninitialized);
ST numberOfActiveOMPThreads = GetNumberOfOmpThreads(IsSPMDExecutionMode);
// All warps that are in excess of the maximum requested, do
// not execute the loop
PRINT(LD_LOOP,
"OMP Thread %d: schedule type %d, chunk size = %lld, mytid "
"%d, num tids %d\n",
GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized),
schedtype, P64(chunk),
GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized),
GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized));
ASSERT0(
LT_FUSSY,
(GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized)) <
(GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized)),
"current thread is not needed here; error");
(int)gtid, (int)schedtype, (long long)chunk, (int)gtid,
(int)numberOfActiveOMPThreads);
ASSERT0(LT_FUSSY, gtid < numberOfActiveOMPThreads,
"current thread is not needed here; error");
// copy
int lastiter = 0;
T lb = *plower;
T ub = *pupper;
ST stride = *pstride;
T entityId, numberOfEntities;
// init
switch (schedtype) {
switch (SCHEDULE_WITHOUT_MODIFIERS(schedtype)) {
case kmp_sched_static_chunk: {
if (chunk > 0) {
entityId =
GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized);
numberOfEntities = GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized);
ForStaticChunk(lastiter, lb, ub, stride, chunk, entityId,
numberOfEntities);
ForStaticChunk(lastiter, lb, ub, stride, chunk, gtid,
numberOfActiveOMPThreads);
break;
}
} // note: if chunk <=0, use nochunk
case kmp_sched_static_balanced_chunk: {
if (chunk > 0) {
// round up to make sure the chunk is enough to cover all iterations
T tripCount = ub - lb + 1; // +1 because ub is inclusive
T span = (tripCount + numberOfActiveOMPThreads - 1) /
numberOfActiveOMPThreads;
// perform chunk adjustment
chunk = (span + chunk - 1) & ~(chunk - 1);
ASSERT0(LT_FUSSY, ub >= lb, "ub must be >= lb.");
T oldUb = ub;
ForStaticChunk(lastiter, lb, ub, stride, chunk, gtid,
numberOfActiveOMPThreads);
if (ub > oldUb)
ub = oldUb;
break;
}
} // note: if chunk <=0, use nochunk
case kmp_sched_static_nochunk: {
entityId =
GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized);
numberOfEntities = GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized);
ForStaticNoChunk(lastiter, lb, ub, stride, chunk, entityId,
numberOfEntities);
ForStaticNoChunk(lastiter, lb, ub, stride, chunk, gtid,
numberOfActiveOMPThreads);
break;
}
case kmp_sched_distr_static_chunk: {
if (chunk > 0) {
entityId = GetOmpTeamId();
numberOfEntities = GetNumberOfOmpTeams();
ForStaticChunk(lastiter, lb, ub, stride, chunk, entityId,
numberOfEntities);
ForStaticChunk(lastiter, lb, ub, stride, chunk, GetOmpTeamId(),
GetNumberOfOmpTeams());
break;
} // note: if chunk <=0, use nochunk
}
case kmp_sched_distr_static_nochunk: {
entityId = GetOmpTeamId();
numberOfEntities = GetNumberOfOmpTeams();
ForStaticNoChunk(lastiter, lb, ub, stride, chunk, entityId,
numberOfEntities);
ForStaticNoChunk(lastiter, lb, ub, stride, chunk, GetOmpTeamId(),
GetNumberOfOmpTeams());
break;
}
case kmp_sched_distr_static_chunk_sched_static_chunkone: {
entityId =
GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized) *
GetOmpTeamId() +
GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized);
numberOfEntities = GetNumberOfOmpTeams() *
GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized);
ForStaticChunk(lastiter, lb, ub, stride, chunk, entityId,
numberOfEntities);
ForStaticChunk(lastiter, lb, ub, stride, chunk,
numberOfActiveOMPThreads * GetOmpTeamId() + gtid,
GetNumberOfOmpTeams() * numberOfActiveOMPThreads);
break;
}
default: {
ASSERT(LT_FUSSY, FALSE, "unknown schedtype %d", schedtype);
ASSERT(LT_FUSSY, FALSE, "unknown schedtype %d", (int)schedtype);
PRINT(LD_LOOP, "unknown schedtype %d, revert back to static chunk\n",
schedtype);
entityId =
GetOmpThreadId(tid, IsSPMDExecutionMode, IsRuntimeUninitialized);
numberOfEntities = GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized);
ForStaticChunk(lastiter, lb, ub, stride, chunk, entityId,
numberOfEntities);
(int)schedtype);
ForStaticChunk(lastiter, lb, ub, stride, chunk, gtid,
numberOfActiveOMPThreads);
break;
}
}
// copy back
@@ -200,11 +184,11 @@ public:
*pupper = ub;
*pstride = stride;
PRINT(LD_LOOP,
"Got sched: Active %d, total %d: lb %lld, ub %lld, stride %lld\n",
GetNumberOfOmpThreads(tid, IsSPMDExecutionMode,
IsRuntimeUninitialized),
GetNumberOfWorkersInTeam(), P64(*plower), P64(*pupper),
P64(*pstride));
"Got sched: Active %d, total %d: lb %lld, ub %lld, stride %lld, last "
"%d\n",
(int)numberOfActiveOMPThreads, (int)GetNumberOfWorkersInTeam(),
(long long)(*plower), (long long)(*pupper), (long long)(*pstride),
(int)lastiter);
}
////////////////////////////////////////////////////////////////////////////////
@@ -215,18 +199,21 @@ public:
schedule <= kmp_sched_ordered_last;
}
INLINE static void dispatch_init(kmp_Indent *loc, int32_t threadId,
INLINE static void dispatch_init(kmp_Ident *loc, int32_t threadId,
kmp_sched_t schedule, T lb, T ub, ST st,
ST chunk) {
int tid = GetLogicalThreadIdInBlock();
if (checkRuntimeUninitialized(loc)) {
// In SPMD mode no need to check parallelism level - dynamic scheduling
// may appear only in L2 parallel regions with lightweight runtime.
ASSERT0(LT_FUSSY, checkSPMDMode(loc), "Expected non-SPMD mode.");
return;
}
int tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor(tid);
T tnum = currTaskDescr->ThreadsInTeam();
T tnum = GetNumberOfOmpThreads(checkSPMDMode(loc));
T tripCount = ub - lb + 1; // +1 because ub is inclusive
ASSERT0(
LT_FUSSY,
GetOmpThreadId(tid, isSPMDMode(), isRuntimeUninitialized()) <
GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized()),
"current thread is not needed here; error");
ASSERT0(LT_FUSSY, threadId < tnum,
"current thread is not needed here; error");
/* Currently just ignore the monotonic and non-monotonic modifiers
* (the compiler isn't producing them * yet anyway).
@@ -244,7 +231,7 @@ public:
__kmpc_barrier(loc, threadId);
PRINT(LD_LOOP,
"go sequential as tnum=%ld, trip count %lld, ordered sched=%d\n",
(long)tnum, P64(tripCount), schedule);
(long)tnum, (long long)tripCount, (int)schedule);
schedule = kmp_sched_static_chunk;
chunk = tripCount; // one thread gets the whole loop
} else if (schedule == kmp_sched_runtime) {
@@ -270,18 +257,20 @@ public:
break;
}
}
PRINT(LD_LOOP, "Runtime sched is %d with chunk %lld\n", schedule,
P64(chunk));
PRINT(LD_LOOP, "Runtime sched is %d with chunk %lld\n", (int)schedule,
(long long)chunk);
} else if (schedule == kmp_sched_auto) {
schedule = kmp_sched_static_chunk;
chunk = 1;
PRINT(LD_LOOP, "Auto sched is %d with chunk %lld\n", schedule,
P64(chunk));
PRINT(LD_LOOP, "Auto sched is %d with chunk %lld\n", (int)schedule,
(long long)chunk);
} else {
PRINT(LD_LOOP, "Dyn sched is %d with chunk %lld\n", schedule, P64(chunk));
PRINT(LD_LOOP, "Dyn sched is %d with chunk %lld\n", (int)schedule,
(long long)chunk);
ASSERT(LT_FUSSY,
schedule == kmp_sched_dynamic || schedule == kmp_sched_guided,
"unknown schedule %d & chunk %lld\n", schedule, P64(chunk));
"unknown schedule %d & chunk %lld\n", (int)schedule,
(long long)chunk);
}
// init schedules
@@ -294,9 +283,7 @@ public:
// compute static chunk
ST stride;
int lastiter = 0;
ForStaticChunk(
lastiter, lb, ub, stride, chunk,
GetOmpThreadId(tid, isSPMDMode(), isRuntimeUninitialized()), tnum);
ForStaticChunk(lastiter, lb, ub, stride, chunk, threadId, tnum);
// save computed params
omptarget_nvptx_threadPrivateContext->Chunk(tid) = chunk;
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid) = lb;
@@ -304,11 +291,44 @@ public:
PRINT(LD_LOOP,
"dispatch init (static chunk) : num threads = %d, ub = %" PRId64
", next lower bound = %llu, stride = %llu\n",
GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized()),
(int)tnum,
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid),
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
omptarget_nvptx_threadPrivateContext->Stride(tid));
(unsigned long long)
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
(unsigned long long)omptarget_nvptx_threadPrivateContext->Stride(
tid));
} else if (schedule == kmp_sched_static_balanced_chunk) {
ASSERT0(LT_FUSSY, chunk > 0, "bad chunk value");
// save sched state
omptarget_nvptx_threadPrivateContext->ScheduleType(tid) = schedule;
// save ub
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid) = ub;
// compute static chunk
ST stride;
int lastiter = 0;
// round up to make sure the chunk is enough to cover all iterations
T span = (tripCount + tnum - 1) / tnum;
// perform chunk adjustment
chunk = (span + chunk - 1) & ~(chunk - 1);
T oldUb = ub;
ForStaticChunk(lastiter, lb, ub, stride, chunk, threadId, tnum);
ASSERT0(LT_FUSSY, ub >= lb, "ub must be >= lb.");
if (ub > oldUb)
ub = oldUb;
// save computed params
omptarget_nvptx_threadPrivateContext->Chunk(tid) = chunk;
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid) = lb;
omptarget_nvptx_threadPrivateContext->Stride(tid) = stride;
PRINT(LD_LOOP,
"dispatch init (static chunk) : num threads = %d, ub = %" PRId64
", next lower bound = %llu, stride = %llu\n",
(int)tnum,
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid),
(unsigned long long)
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
(unsigned long long)omptarget_nvptx_threadPrivateContext->Stride(
tid));
} else if (schedule == kmp_sched_static_nochunk) {
ASSERT0(LT_FUSSY, chunk == 0, "bad chunk value");
// save sched state
@@ -318,9 +338,7 @@ public:
// compute static chunk
ST stride;
int lastiter = 0;
ForStaticNoChunk(
lastiter, lb, ub, stride, chunk,
GetOmpThreadId(tid, isSPMDMode(), isRuntimeUninitialized()), tnum);
ForStaticNoChunk(lastiter, lb, ub, stride, chunk, threadId, tnum);
// save computed params
omptarget_nvptx_threadPrivateContext->Chunk(tid) = chunk;
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid) = lb;
@@ -328,43 +346,69 @@ public:
PRINT(LD_LOOP,
"dispatch init (static nochunk) : num threads = %d, ub = %" PRId64
", next lower bound = %llu, stride = %llu\n",
GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized()),
(int)tnum,
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid),
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
omptarget_nvptx_threadPrivateContext->Stride(tid));
(unsigned long long)
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
(unsigned long long)omptarget_nvptx_threadPrivateContext->Stride(
tid));
} else if (schedule == kmp_sched_dynamic || schedule == kmp_sched_guided) {
__kmpc_barrier(loc, threadId);
// save sched state
int teamId = GetOmpTeamId();
// save data
omptarget_nvptx_threadPrivateContext->ScheduleType(tid) = schedule;
if (GetThreadIdInBlock() == 0) {
if (chunk < 1)
chunk = 1;
omptarget_nvptx_threadPrivateContext->Chunk(teamId) = chunk;
omptarget_nvptx_threadPrivateContext->LoopUpperBound(teamId) = ub;
omptarget_nvptx_threadPrivateContext->NextLowerBound(teamId) = lb;
if (chunk < 1)
chunk = 1;
omptarget_nvptx_threadPrivateContext->Chunk(tid) = chunk;
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid) = ub;
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid) = lb;
__kmpc_barrier(loc, threadId);
if (tid == 0) {
omptarget_nvptx_threadPrivateContext->Cnt() = 0;
__threadfence_block();
}
__kmpc_barrier(loc, threadId);
PRINT(LD_LOOP,
"dispatch init (dyn) : num threads = %d, lb = %llu, ub = %" PRId64
", chunk %" PRIu64 "\n",
GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized()),
omptarget_nvptx_threadPrivateContext->NextLowerBound(teamId),
omptarget_nvptx_threadPrivateContext->LoopUpperBound(teamId),
omptarget_nvptx_threadPrivateContext->Chunk(teamId));
(int)tnum,
(unsigned long long)
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid),
omptarget_nvptx_threadPrivateContext->Chunk(tid));
}
}
////////////////////////////////////////////////////////////////////////////////
// Support for dispatch next
INLINE static uint64_t Shuffle(__kmpc_impl_lanemask_t active, int64_t val,
int leader) {
uint32_t lo, hi;
__kmpc_impl_unpack(val, lo, hi);
hi = __kmpc_impl_shfl_sync(active, hi, leader);
lo = __kmpc_impl_shfl_sync(active, lo, leader);
return __kmpc_impl_pack(lo, hi);
}
INLINE static uint64_t NextIter() {
__kmpc_impl_lanemask_t active = __kmpc_impl_activemask();
uint32_t leader = __kmpc_impl_ffs(active) - 1;
uint32_t change = __kmpc_impl_popc(active);
__kmpc_impl_lanemask_t lane_mask_lt = __kmpc_impl_lanemask_lt();
unsigned int rank = __kmpc_impl_popc(active & lane_mask_lt);
uint64_t warp_res;
if (rank == 0) {
warp_res = atomicAdd(
(unsigned long long *)&omptarget_nvptx_threadPrivateContext->Cnt(),
change);
}
warp_res = Shuffle(active, warp_res, leader);
return warp_res + rank;
}
INLINE static int DynamicNextChunk(T &lb, T &ub, T chunkSize,
int64_t &loopLowerBound,
T loopUpperBound) {
// calculate lower bound for all lanes in the warp
lb = atomicAdd((unsigned long long *)&loopLowerBound,
(unsigned long long)chunkSize);
T loopLowerBound, T loopUpperBound) {
T N = NextIter();
lb = loopLowerBound + N * chunkSize;
ub = lb + chunkSize - 1; // Clang uses i <= ub
// 3 result cases:
@@ -374,39 +418,42 @@ public:
// c. lb and ub >= loopUpperBound: empty chunk --> FINISHED
// a.
if (lb <= loopUpperBound && ub < loopUpperBound) {
PRINT(LD_LOOPD, "lb %lld, ub %lld, loop ub %lld; not finished\n", P64(lb),
P64(ub), P64(loopUpperBound));
PRINT(LD_LOOPD, "lb %lld, ub %lld, loop ub %lld; not finished\n",
(long long)lb, (long long)ub, (long long)loopUpperBound);
return NOT_FINISHED;
}
// b.
if (lb <= loopUpperBound) {
PRINT(LD_LOOPD, "lb %lld, ub %lld, loop ub %lld; clip to loop ub\n",
P64(lb), P64(ub), P64(loopUpperBound));
(long long)lb, (long long)ub, (long long)loopUpperBound);
ub = loopUpperBound;
return LAST_CHUNK;
}
// c. if we are here, we are in case 'c'
lb = loopUpperBound + 2;
ub = loopUpperBound + 1;
PRINT(LD_LOOPD, "lb %lld, ub %lld, loop ub %lld; finished\n", P64(lb),
P64(ub), P64(loopUpperBound));
PRINT(LD_LOOPD, "lb %lld, ub %lld, loop ub %lld; finished\n", (long long)lb,
(long long)ub, (long long)loopUpperBound);
return FINISHED;
}
// On Pascal, with inlining of the runtime into the user application,
// this code deadlocks. This is probably because different threads
// in a warp cannot make independent progress.
NOINLINE static int dispatch_next(int32_t *plast, T *plower, T *pupper,
ST *pstride) {
INLINE static int dispatch_next(kmp_Ident *loc, int32_t gtid, int32_t *plast,
T *plower, T *pupper, ST *pstride) {
if (checkRuntimeUninitialized(loc)) {
// In SPMD mode no need to check parallelism level - dynamic scheduling
// may appear only in L2 parallel regions with lightweight runtime.
ASSERT0(LT_FUSSY, checkSPMDMode(loc), "Expected non-SPMD mode.");
if (*plast)
return DISPATCH_FINISHED;
*plast = 1;
return DISPATCH_NOTFINISHED;
}
// ID of a thread in its own warp
// automatically selects thread or warp ID based on selected implementation
int tid = GetLogicalThreadIdInBlock();
ASSERT0(
LT_FUSSY,
GetOmpThreadId(tid, isSPMDMode(), isRuntimeUninitialized()) <
GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized()),
"current thread is not needed here; error");
int tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
ASSERT0(LT_FUSSY, gtid < GetNumberOfOmpThreads(checkSPMDMode(loc)),
"current thread is not needed here; error");
// retrieve schedule
kmp_sched_t schedule =
omptarget_nvptx_threadPrivateContext->ScheduleType(tid);
@@ -419,7 +466,7 @@ public:
// finished?
if (myLb > ub) {
PRINT(LD_LOOP, "static loop finished with myLb %lld, ub %lld\n",
P64(myLb), P64(ub));
(long long)myLb, (long long)ub);
return DISPATCH_FINISHED;
}
// not finished, save current bounds
@@ -435,18 +482,17 @@ public:
ST stride = omptarget_nvptx_threadPrivateContext->Stride(tid);
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid) = myLb + stride;
PRINT(LD_LOOP, "static loop continues with myLb %lld, myUb %lld\n",
P64(*plower), P64(*pupper));
(long long)*plower, (long long)*pupper);
return DISPATCH_NOTFINISHED;
}
ASSERT0(LT_FUSSY,
schedule == kmp_sched_dynamic || schedule == kmp_sched_guided,
"bad sched");
T myLb, myUb;
int teamId = GetOmpTeamId();
int finished = DynamicNextChunk(
myLb, myUb, omptarget_nvptx_threadPrivateContext->Chunk(teamId),
omptarget_nvptx_threadPrivateContext->NextLowerBound(teamId),
omptarget_nvptx_threadPrivateContext->LoopUpperBound(teamId));
myLb, myUb, omptarget_nvptx_threadPrivateContext->Chunk(tid),
omptarget_nvptx_threadPrivateContext->NextLowerBound(tid),
omptarget_nvptx_threadPrivateContext->LoopUpperBound(tid));
if (finished == FINISHED)
return DISPATCH_FINISHED;
@@ -458,10 +504,11 @@ public:
*pstride = 1;
PRINT(LD_LOOP,
"Got sched: active %d, total %d: lb %lld, ub %lld, stride = %lld\n",
GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized()),
GetNumberOfWorkersInTeam(), P64(*plower), P64(*pupper),
P64(*pstride));
"Got sched: active %d, total %d: lb %lld, ub %lld, stride = %lld, "
"last %d\n",
(int)GetNumberOfOmpThreads(isSPMDMode()),
(int)GetNumberOfWorkersInTeam(), (long long)*plower,
(long long)*pupper, (long long)*pstride, (int)*plast);
return DISPATCH_NOTFINISHED;
}
@@ -479,7 +526,7 @@ public:
////////////////////////////////////////////////////////////////////////////////
// init
EXTERN void __kmpc_dispatch_init_4(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_dispatch_init_4(kmp_Ident *loc, int32_t tid,
int32_t schedule, int32_t lb, int32_t ub,
int32_t st, int32_t chunk) {
PRINT0(LD_IO, "call kmpc_dispatch_init_4\n");
@@ -487,7 +534,7 @@ EXTERN void __kmpc_dispatch_init_4(kmp_Indent *loc, int32_t tid,
loc, tid, (kmp_sched_t)schedule, lb, ub, st, chunk);
}
EXTERN void __kmpc_dispatch_init_4u(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_dispatch_init_4u(kmp_Ident *loc, int32_t tid,
int32_t schedule, uint32_t lb, uint32_t ub,
int32_t st, int32_t chunk) {
PRINT0(LD_IO, "call kmpc_dispatch_init_4u\n");
@@ -495,7 +542,7 @@ EXTERN void __kmpc_dispatch_init_4u(kmp_Indent *loc, int32_t tid,
loc, tid, (kmp_sched_t)schedule, lb, ub, st, chunk);
}
EXTERN void __kmpc_dispatch_init_8(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_dispatch_init_8(kmp_Ident *loc, int32_t tid,
int32_t schedule, int64_t lb, int64_t ub,
int64_t st, int64_t chunk) {
PRINT0(LD_IO, "call kmpc_dispatch_init_8\n");
@@ -503,7 +550,7 @@ EXTERN void __kmpc_dispatch_init_8(kmp_Indent *loc, int32_t tid,
loc, tid, (kmp_sched_t)schedule, lb, ub, st, chunk);
}
EXTERN void __kmpc_dispatch_init_8u(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_dispatch_init_8u(kmp_Ident *loc, int32_t tid,
int32_t schedule, uint64_t lb, uint64_t ub,
int64_t st, int64_t chunk) {
PRINT0(LD_IO, "call kmpc_dispatch_init_8u\n");
@@ -512,53 +559,53 @@ EXTERN void __kmpc_dispatch_init_8u(kmp_Indent *loc, int32_t tid,
}
// next
EXTERN int __kmpc_dispatch_next_4(kmp_Indent *loc, int32_t tid, int32_t *p_last,
EXTERN int __kmpc_dispatch_next_4(kmp_Ident *loc, int32_t tid, int32_t *p_last,
int32_t *p_lb, int32_t *p_ub, int32_t *p_st) {
PRINT0(LD_IO, "call kmpc_dispatch_next_4\n");
return omptarget_nvptx_LoopSupport<int32_t, int32_t>::dispatch_next(
p_last, p_lb, p_ub, p_st);
loc, tid, p_last, p_lb, p_ub, p_st);
}
EXTERN int __kmpc_dispatch_next_4u(kmp_Indent *loc, int32_t tid,
EXTERN int __kmpc_dispatch_next_4u(kmp_Ident *loc, int32_t tid,
int32_t *p_last, uint32_t *p_lb,
uint32_t *p_ub, int32_t *p_st) {
PRINT0(LD_IO, "call kmpc_dispatch_next_4u\n");
return omptarget_nvptx_LoopSupport<uint32_t, int32_t>::dispatch_next(
p_last, p_lb, p_ub, p_st);
loc, tid, p_last, p_lb, p_ub, p_st);
}
EXTERN int __kmpc_dispatch_next_8(kmp_Indent *loc, int32_t tid, int32_t *p_last,
EXTERN int __kmpc_dispatch_next_8(kmp_Ident *loc, int32_t tid, int32_t *p_last,
int64_t *p_lb, int64_t *p_ub, int64_t *p_st) {
PRINT0(LD_IO, "call kmpc_dispatch_next_8\n");
return omptarget_nvptx_LoopSupport<int64_t, int64_t>::dispatch_next(
p_last, p_lb, p_ub, p_st);
loc, tid, p_last, p_lb, p_ub, p_st);
}
EXTERN int __kmpc_dispatch_next_8u(kmp_Indent *loc, int32_t tid,
EXTERN int __kmpc_dispatch_next_8u(kmp_Ident *loc, int32_t tid,
int32_t *p_last, uint64_t *p_lb,
uint64_t *p_ub, int64_t *p_st) {
PRINT0(LD_IO, "call kmpc_dispatch_next_8u\n");
return omptarget_nvptx_LoopSupport<uint64_t, int64_t>::dispatch_next(
p_last, p_lb, p_ub, p_st);
loc, tid, p_last, p_lb, p_ub, p_st);
}
// fini
EXTERN void __kmpc_dispatch_fini_4(kmp_Indent *loc, int32_t tid) {
EXTERN void __kmpc_dispatch_fini_4(kmp_Ident *loc, int32_t tid) {
PRINT0(LD_IO, "call kmpc_dispatch_fini_4\n");
omptarget_nvptx_LoopSupport<int32_t, int32_t>::dispatch_fini();
}
EXTERN void __kmpc_dispatch_fini_4u(kmp_Indent *loc, int32_t tid) {
EXTERN void __kmpc_dispatch_fini_4u(kmp_Ident *loc, int32_t tid) {
PRINT0(LD_IO, "call kmpc_dispatch_fini_4u\n");
omptarget_nvptx_LoopSupport<uint32_t, int32_t>::dispatch_fini();
}
EXTERN void __kmpc_dispatch_fini_8(kmp_Indent *loc, int32_t tid) {
EXTERN void __kmpc_dispatch_fini_8(kmp_Ident *loc, int32_t tid) {
PRINT0(LD_IO, "call kmpc_dispatch_fini_8\n");
omptarget_nvptx_LoopSupport<int64_t, int64_t>::dispatch_fini();
}
EXTERN void __kmpc_dispatch_fini_8u(kmp_Indent *loc, int32_t tid) {
EXTERN void __kmpc_dispatch_fini_8u(kmp_Ident *loc, int32_t tid) {
PRINT0(LD_IO, "call kmpc_dispatch_fini_8u\n");
omptarget_nvptx_LoopSupport<uint64_t, int64_t>::dispatch_fini();
}
@@ -567,151 +614,143 @@ EXTERN void __kmpc_dispatch_fini_8u(kmp_Indent *loc, int32_t tid) {
// KMP interface implementation (static loops)
////////////////////////////////////////////////////////////////////////////////
EXTERN void __kmpc_for_static_init_4(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_4(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype, int32_t *plastiter,
int32_t *plower, int32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_4\n");
omptarget_nvptx_LoopSupport<int32_t, int32_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk, isSPMDMode(),
isRuntimeUninitialized());
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
checkSPMDMode(loc));
}
EXTERN void __kmpc_for_static_init_4u(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_4u(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype, int32_t *plastiter,
uint32_t *plower, uint32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_4u\n");
omptarget_nvptx_LoopSupport<uint32_t, int32_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk, isSPMDMode(),
isRuntimeUninitialized());
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
checkSPMDMode(loc));
}
EXTERN void __kmpc_for_static_init_8(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_8(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype, int32_t *plastiter,
int64_t *plower, int64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_8\n");
omptarget_nvptx_LoopSupport<int64_t, int64_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk, isSPMDMode(),
isRuntimeUninitialized());
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
checkSPMDMode(loc));
}
EXTERN void __kmpc_for_static_init_8u(kmp_Indent *loc, int32_t global_tid,
EXTERN void __kmpc_for_static_init_8u(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype, int32_t *plastiter,
uint64_t *plower, uint64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_8u\n");
omptarget_nvptx_LoopSupport<uint64_t, int64_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk, isSPMDMode(),
isRuntimeUninitialized());
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
checkSPMDMode(loc));
}
EXTERN
void __kmpc_for_static_init_4_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_4_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype, int32_t *plastiter,
int32_t *plower, int32_t *pupper,
int32_t *pstride, int32_t incr,
int32_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_4_simple_spmd\n");
omptarget_nvptx_LoopSupport<int32_t, int32_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true);
}
EXTERN
void __kmpc_for_static_init_4u_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_4u_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype,
int32_t *plastiter, uint32_t *plower,
uint32_t *pupper, int32_t *pstride,
int32_t incr, int32_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_4u_simple_spmd\n");
omptarget_nvptx_LoopSupport<uint32_t, int32_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true);
}
EXTERN
void __kmpc_for_static_init_8_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_8_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype, int32_t *plastiter,
int64_t *plower, int64_t *pupper,
int64_t *pstride, int64_t incr,
int64_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_8_simple_spmd\n");
omptarget_nvptx_LoopSupport<int64_t, int64_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true);
}
EXTERN
void __kmpc_for_static_init_8u_simple_spmd(kmp_Indent *loc, int32_t global_tid,
void __kmpc_for_static_init_8u_simple_spmd(kmp_Ident *loc, int32_t global_tid,
int32_t schedtype,
int32_t *plastiter, uint64_t *plower,
uint64_t *pupper, int64_t *pstride,
int64_t incr, int64_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_8u_simple_spmd\n");
omptarget_nvptx_LoopSupport<uint64_t, int64_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/true);
}
EXTERN
void __kmpc_for_static_init_4_simple_generic(
kmp_Indent *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
kmp_Ident *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
int32_t *plower, int32_t *pupper, int32_t *pstride, int32_t incr,
int32_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_4_simple_generic\n");
omptarget_nvptx_LoopSupport<int32_t, int32_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false);
}
EXTERN
void __kmpc_for_static_init_4u_simple_generic(
kmp_Indent *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
kmp_Ident *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
uint32_t *plower, uint32_t *pupper, int32_t *pstride, int32_t incr,
int32_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_4u_simple_generic\n");
omptarget_nvptx_LoopSupport<uint32_t, int32_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false);
}
EXTERN
void __kmpc_for_static_init_8_simple_generic(
kmp_Indent *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
kmp_Ident *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
int64_t *plower, int64_t *pupper, int64_t *pstride, int64_t incr,
int64_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_8_simple_generic\n");
omptarget_nvptx_LoopSupport<int64_t, int64_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false);
}
EXTERN
void __kmpc_for_static_init_8u_simple_generic(
kmp_Indent *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
kmp_Ident *loc, int32_t global_tid, int32_t schedtype, int32_t *plastiter,
uint64_t *plower, uint64_t *pupper, int64_t *pstride, int64_t incr,
int64_t chunk) {
PRINT0(LD_IO, "call kmpc_for_static_init_8u_simple_generic\n");
omptarget_nvptx_LoopSupport<uint64_t, int64_t>::for_static_init(
schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false,
/*IsRuntimeUninitialized=*/true);
global_tid, schedtype, plastiter, plower, pupper, pstride, chunk,
/*IsSPMDExecutionMode=*/false);
}
EXTERN void __kmpc_for_static_fini(kmp_Indent *loc, int32_t global_tid) {
EXTERN void __kmpc_for_static_fini(kmp_Ident *loc, int32_t global_tid) {
PRINT0(LD_IO, "call kmpc_for_static_fini\n");
}
@@ -733,19 +772,18 @@ INLINE void syncWorkersInGenericMode(uint32_t NumThreads) {
}
}; // namespace
EXTERN void __kmpc_reduce_conditional_lastprivate(kmp_Indent *loc, int32_t gtid,
EXTERN void __kmpc_reduce_conditional_lastprivate(kmp_Ident *loc, int32_t gtid,
int32_t varNum, void *array) {
PRINT0(LD_IO, "call to __kmpc_reduce_conditional_lastprivate(...)\n");
ASSERT0(LT_FUSSY, checkRuntimeInitialized(loc),
"Expected non-SPMD mode + initialized runtime.");
omptarget_nvptx_TeamDescr &teamDescr = getMyTeamDescriptor();
int tid = GetOmpThreadId(GetLogicalThreadIdInBlock(), isSPMDMode(),
isRuntimeUninitialized());
uint32_t NumThreads = GetNumberOfOmpThreads(
GetLogicalThreadIdInBlock(), isSPMDMode(), isRuntimeUninitialized());
uint32_t NumThreads = GetNumberOfOmpThreads(checkSPMDMode(loc));
uint64_t *Buffer = teamDescr.getLastprivateIterBuffer();
for (unsigned i = 0; i < varNum; i++) {
// Reset buffer.
if (tid == 0)
if (gtid == 0)
*Buffer = 0; // Reset to minimum loop iteration value.
// Barrier.
@@ -0,0 +1,17 @@
//===--- nvptx_interface.h - OpenMP interface definitions -------- CUDA -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _NVPTX_INTERFACE_H_
#define _NVPTX_INTERFACE_H_
#include <stdint.h>
#define EXTERN extern "C" __device__
typedef uint32_t __kmpc_impl_lanemask_t;
#endif
+12 -4
View File
@@ -1,9 +1,8 @@
//===------------ omp_data.cu - NVPTX OpenMP GPU objects --------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -27,6 +26,15 @@ __device__
omptarget_nvptx_Queue<omptarget_nvptx_ThreadPrivateContext, OMP_STATE_COUNT>
omptarget_nvptx_device_State[MAX_SM];
__device__ omptarget_nvptx_SimpleMemoryManager
omptarget_nvptx_simpleMemoryManager;
__device__ __shared__ uint32_t usedMemIdx;
__device__ __shared__ uint32_t usedSlotIdx;
__device__ __shared__ uint8_t parallelLevel[MAX_THREADS_PER_TEAM / WARPSIZE];
__device__ __shared__ uint16_t threadLimit;
__device__ __shared__ uint16_t threadsInTeam;
__device__ __shared__ uint16_t nThreads;
// Pointer to this team's OpenMP state object
__device__ __shared__
omptarget_nvptx_ThreadPrivateContext *omptarget_nvptx_threadPrivateContext;
@@ -1,9 +1,8 @@
//===--- omptarget-nvptx.cu - NVPTX OpenMP GPU initialization ---- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -12,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "omptarget-nvptx.h"
#include "target_impl.h"
////////////////////////////////////////////////////////////////////////////////
// global data tables
@@ -21,23 +21,11 @@ extern __device__
omptarget_nvptx_Queue<omptarget_nvptx_ThreadPrivateContext, OMP_STATE_COUNT>
omptarget_nvptx_device_State[MAX_SM];
extern __device__ __shared__
omptarget_nvptx_ThreadPrivateContext *omptarget_nvptx_threadPrivateContext;
//
// The team master sets the outlined function and its arguments in these
// variables to communicate with the workers. Since they are in shared memory,
// there is one copy of these variables for each kernel, instance, and team.
//
extern volatile __device__ __shared__ omptarget_nvptx_WorkFn
omptarget_nvptx_workFn;
extern __device__ __shared__ uint32_t execution_param;
////////////////////////////////////////////////////////////////////////////////
// init entry points
////////////////////////////////////////////////////////////////////////////////
INLINE unsigned smid() {
INLINE static unsigned smid() {
unsigned id;
asm("mov.u32 %0, %%smid;" : "=r"(id));
return id;
@@ -53,13 +41,11 @@ EXTERN void __kmpc_kernel_init_params(void *Ptr) {
EXTERN void __kmpc_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime) {
PRINT(LD_IO, "call to __kmpc_kernel_init with version %f\n",
OMPTARGET_NVPTX_VERSION);
if (!RequiresOMPRuntime) {
// If OMP runtime is not required don't initialize OMP state.
setExecutionParameters(Generic, RuntimeUninitialized);
return;
}
ASSERT0(LT_FUSSY, RequiresOMPRuntime,
"Generic always requires initialized runtime.");
setExecutionParameters(Generic, RuntimeInitialized);
for (int I = 0; I < MAX_THREADS_PER_TEAM / WARPSIZE; ++I)
parallelLevel[I] = 0;
int threadIdInBlock = GetThreadIdInBlock();
ASSERT0(LT_FUSSY, threadIdInBlock == GetMasterThreadID(),
@@ -68,14 +54,12 @@ EXTERN void __kmpc_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime) {
// Get a state object from the queue.
int slot = smid() % MAX_SM;
usedSlotIdx = slot;
omptarget_nvptx_threadPrivateContext =
omptarget_nvptx_device_State[slot].Dequeue();
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
omptarget_nvptx_threadPrivateContext->SetSourceQueue(slot);
#endif
// init thread private
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(/*isSPMDExecutionMode=*/false);
omptarget_nvptx_threadPrivateContext->InitThreadPrivateContext(threadId);
// init team context
@@ -90,21 +74,18 @@ EXTERN void __kmpc_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime) {
// set number of threads and thread limit in team to started value
omptarget_nvptx_TaskDescr *currTaskDescr =
omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(threadId);
currTaskDescr->NThreads() = GetNumberOfWorkersInTeam();
currTaskDescr->ThreadLimit() = ThreadLimit;
nThreads = GetNumberOfWorkersInTeam();
threadLimit = ThreadLimit;
}
EXTERN void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized) {
if (IsOMPRuntimeInitialized) {
// Enqueue omp state object for use by another team.
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
int slot = omptarget_nvptx_threadPrivateContext->GetSourceQueue();
#else
int slot = smid() % MAX_SM;
#endif
omptarget_nvptx_device_State[slot].Enqueue(
omptarget_nvptx_threadPrivateContext);
}
PRINT0(LD_IO, "call to __kmpc_kernel_deinit\n");
ASSERT0(LT_FUSSY, IsOMPRuntimeInitialized,
"Generic always requires initialized runtime.");
// Enqueue omp state object for use by another team.
int slot = usedSlotIdx;
omptarget_nvptx_device_State[slot].Enqueue(
omptarget_nvptx_threadPrivateContext);
// Done with work. Kill the workers.
omptarget_nvptx_workFn = 0;
}
@@ -113,33 +94,39 @@ EXTERN void __kmpc_spmd_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime,
int16_t RequiresDataSharing) {
PRINT0(LD_IO, "call to __kmpc_spmd_kernel_init\n");
setExecutionParameters(Spmd, RequiresOMPRuntime ? RuntimeInitialized
: RuntimeUninitialized);
int threadId = GetThreadIdInBlock();
if (threadId == 0) {
usedSlotIdx = smid() % MAX_SM;
parallelLevel[0] =
1 + (GetNumberOfThreadsInBlock() > 1 ? OMP_ACTIVE_PARALLEL_LEVEL : 0);
} else if (GetLaneId() == 0) {
parallelLevel[GetWarpId()] =
1 + (GetNumberOfThreadsInBlock() > 1 ? OMP_ACTIVE_PARALLEL_LEVEL : 0);
}
if (!RequiresOMPRuntime) {
// If OMP runtime is not required don't initialize OMP state.
setExecutionParameters(Spmd, RuntimeUninitialized);
// Runtime is not required - exit.
__kmpc_impl_syncthreads();
return;
}
setExecutionParameters(Spmd, RuntimeInitialized);
//
// Team Context Initialization.
//
// In SPMD mode there is no master thread so use any cuda thread for team
// context initialization.
int threadId = GetThreadIdInBlock();
if (threadId == 0) {
// Get a state object from the queue.
int slot = smid() % MAX_SM;
omptarget_nvptx_threadPrivateContext =
omptarget_nvptx_device_State[slot].Dequeue();
omptarget_nvptx_device_State[usedSlotIdx].Dequeue();
omptarget_nvptx_TeamDescr &currTeamDescr = getMyTeamDescriptor();
omptarget_nvptx_WorkDescr &workDescr = getMyWorkDescriptor();
// init team context
currTeamDescr.InitTeamDescr();
// init counters (copy start to init)
workDescr.CounterGroup().Reset();
}
__syncthreads();
__kmpc_impl_syncthreads();
omptarget_nvptx_TeamDescr &currTeamDescr = getMyTeamDescriptor();
omptarget_nvptx_WorkDescr &workDescr = getMyWorkDescriptor();
@@ -150,22 +137,18 @@ EXTERN void __kmpc_spmd_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime,
omptarget_nvptx_TaskDescr *newTaskDescr =
omptarget_nvptx_threadPrivateContext->Level1TaskDescr(threadId);
ASSERT0(LT_FUSSY, newTaskDescr, "expected a task descr");
newTaskDescr->InitLevelOneTaskDescr(ThreadLimit,
currTeamDescr.LevelZeroTaskDescr());
newTaskDescr->ThreadLimit() = ThreadLimit;
newTaskDescr->InitLevelOneTaskDescr(currTeamDescr.LevelZeroTaskDescr());
// install new top descriptor
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(threadId,
newTaskDescr);
// init thread private from init value
workDescr.CounterGroup().Init(
omptarget_nvptx_threadPrivateContext->Priv(threadId));
PRINT(LD_PAR,
"thread will execute parallel region with id %d in a team of "
"%d threads\n",
newTaskDescr->ThreadId(), newTaskDescr->ThreadsInTeam());
(int)newTaskDescr->ThreadId(), (int)ThreadLimit);
if (RequiresDataSharing && threadId % WARPSIZE == 0) {
if (RequiresDataSharing && GetLaneId() == 0) {
// Warp master innitializes data sharing environment.
unsigned WID = threadId / WARPSIZE;
__kmpc_data_sharing_slot *RootS = currTeamDescr.RootS(
@@ -175,14 +158,21 @@ EXTERN void __kmpc_spmd_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime,
}
}
EXTERN void __kmpc_spmd_kernel_deinit() {
EXTERN __attribute__((deprecated)) void __kmpc_spmd_kernel_deinit() {
__kmpc_spmd_kernel_deinit_v2(isRuntimeInitialized());
}
EXTERN void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime) {
// We're not going to pop the task descr stack of each thread since
// there are no more parallel regions in SPMD mode.
__syncthreads();
if (!RequiresOMPRuntime)
return;
__kmpc_impl_syncthreads();
int threadId = GetThreadIdInBlock();
if (threadId == 0) {
// Enqueue omp state object for use by another team.
int slot = smid() % MAX_SM;
int slot = usedSlotIdx;
omptarget_nvptx_device_State[slot].Enqueue(
omptarget_nvptx_threadPrivateContext);
}
@@ -190,5 +180,6 @@ EXTERN void __kmpc_spmd_kernel_deinit() {
// Return true if the current target region is executed in SPMD mode.
EXTERN int8_t __kmpc_is_spmd_exec_mode() {
PRINT0(LD_IO | LD_PAR, "call to __kmpc_is_spmd_exec_mode\n");
return isSPMDMode();
}
@@ -1,9 +1,8 @@
//===---- omptarget-nvptx.h - NVPTX OpenMP GPU initialization ---- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -26,7 +25,6 @@
#include <math.h>
// local includes
#include "counter_group.h"
#include "debug.h" // debug
#include "interface.h" // interfaces with omp, compiler, and user
#include "option.h" // choices we have
@@ -47,23 +45,6 @@
#define BARRIER_COUNTER 0
#define ORDERED_COUNTER 1
// Macros for Cuda intrinsics
// In Cuda 9.0, the *_sync() version takes an extra argument 'mask'.
// Also, __ballot(1) in Cuda 8.0 is replaced with __activemask().
#if defined(CUDART_VERSION) && CUDART_VERSION >= 9000
#define __SHFL_SYNC(mask, var, srcLane) __shfl_sync((mask), (var), (srcLane))
#define __SHFL_DOWN_SYNC(mask, var, delta, width) \
__shfl_down_sync((mask), (var), (delta), (width))
#define __BALLOT_SYNC(mask, predicate) __ballot_sync((mask), (predicate))
#define __ACTIVEMASK() __activemask()
#else
#define __SHFL_SYNC(mask, var, srcLane) __shfl((var), (srcLane))
#define __SHFL_DOWN_SYNC(mask, var, delta, width) \
__shfl_down((var), (delta), (width))
#define __BALLOT_SYNC(mask, predicate) __ballot((predicate))
#define __ACTIVEMASK() __ballot(1)
#endif
// arguments needed for L0 parallelism only.
class omptarget_nvptx_SharedArgs {
public:
@@ -91,7 +72,7 @@ public:
}
}
// Called by all threads.
INLINE void **GetArgs() { return args; };
INLINE void **GetArgs() const { return args; };
private:
// buffer of pre-allocated arguments.
void *buffer[MAX_SHARED_ARGS];
@@ -102,7 +83,8 @@ private:
uint32_t nArgs;
};
extern __device__ __shared__ omptarget_nvptx_SharedArgs omptarget_nvptx_globalArgs;
extern __device__ __shared__ omptarget_nvptx_SharedArgs
omptarget_nvptx_globalArgs;
// Data sharing related quantities, need to match what is used in the compiler.
enum DATA_SHARING_SIZES {
@@ -114,6 +96,8 @@ enum DATA_SHARING_SIZES {
DS_Worker_Warp_Slot_Size = WARPSIZE * DS_Slot_Size,
// The maximum number of warps in use
DS_Max_Warp_Number = 32,
// The size of the preallocated shared memory buffer per team
DS_Shared_Memory_Size = 128,
};
// Data structure to keep in shared memory that traces the current slot, stack,
@@ -122,8 +106,8 @@ enum DATA_SHARING_SIZES {
struct DataSharingStateTy {
__kmpc_data_sharing_slot *SlotPtr[DS_Max_Warp_Number];
void *StackPtr[DS_Max_Warp_Number];
void *FramePtr[DS_Max_Warp_Number];
int32_t ActiveThreads[DS_Max_Warp_Number];
void * volatile FramePtr[DS_Max_Warp_Number];
__kmpc_impl_lanemask_t ActiveThreads[DS_Max_Warp_Number];
};
// Additional worker slot type which is initialized with the default worker slot
// size of 4*32 bytes.
@@ -151,43 +135,31 @@ extern __device__ __shared__ DataSharingStateTy DataSharingState;
class omptarget_nvptx_TaskDescr {
public:
// methods for flags
INLINE omp_sched_t GetRuntimeSched();
INLINE omp_sched_t GetRuntimeSched() const;
INLINE void SetRuntimeSched(omp_sched_t sched);
INLINE int IsDynamic() { return items.flags & TaskDescr_IsDynamic; }
INLINE void SetDynamic() {
items.flags = items.flags | TaskDescr_IsDynamic;
}
INLINE void ClearDynamic() {
items.flags = items.flags & (~TaskDescr_IsDynamic);
}
INLINE int InParallelRegion() { return items.flags & TaskDescr_InPar; }
INLINE int InL2OrHigherParallelRegion() {
INLINE int InParallelRegion() const { return items.flags & TaskDescr_InPar; }
INLINE int InL2OrHigherParallelRegion() const {
return items.flags & TaskDescr_InParL2P;
}
INLINE int IsParallelConstruct() {
INLINE int IsParallelConstruct() const {
return items.flags & TaskDescr_IsParConstr;
}
INLINE int IsTaskConstruct() { return !IsParallelConstruct(); }
INLINE int IsTaskConstruct() const { return !IsParallelConstruct(); }
// methods for other fields
INLINE uint16_t &NThreads() { return items.nthreads; }
INLINE uint16_t &ThreadLimit() { return items.threadlimit; }
INLINE uint16_t &ThreadId() { return items.threadId; }
INLINE uint16_t &ThreadsInTeam() { return items.threadsInTeam; }
INLINE uint64_t &RuntimeChunkSize() { return items.runtimeChunkSize; }
INLINE omptarget_nvptx_TaskDescr *GetPrevTaskDescr() { return prev; }
INLINE omptarget_nvptx_TaskDescr *GetPrevTaskDescr() const { return prev; }
INLINE void SetPrevTaskDescr(omptarget_nvptx_TaskDescr *taskDescr) {
prev = taskDescr;
}
// init & copy
INLINE void InitLevelZeroTaskDescr();
INLINE void InitLevelOneTaskDescr(uint16_t tnum,
omptarget_nvptx_TaskDescr *parentTaskDescr);
INLINE void InitLevelOneTaskDescr(omptarget_nvptx_TaskDescr *parentTaskDescr);
INLINE void Copy(omptarget_nvptx_TaskDescr *sourceTaskDescr);
INLINE void CopyData(omptarget_nvptx_TaskDescr *sourceTaskDescr);
INLINE void CopyParent(omptarget_nvptx_TaskDescr *parentTaskDescr);
INLINE void CopyForExplicitTask(omptarget_nvptx_TaskDescr *parentTaskDescr);
INLINE void CopyToWorkDescr(omptarget_nvptx_TaskDescr *masterTaskDescr,
uint16_t tnum);
INLINE void CopyToWorkDescr(omptarget_nvptx_TaskDescr *masterTaskDescr);
INLINE void CopyFromWorkDescr(omptarget_nvptx_TaskDescr *workTaskDescr);
INLINE void CopyConvergentParent(omptarget_nvptx_TaskDescr *parentTaskDescr,
uint16_t tid, uint16_t tnum);
@@ -195,15 +167,13 @@ public:
INLINE void RestoreLoopData() const;
private:
// bits for flags: (7 used, 1 free)
// bits for flags: (6 used, 2 free)
// 3 bits (SchedMask) for runtime schedule
// 1 bit (IsDynamic) for dynamic schedule (false = static)
// 1 bit (InPar) if this thread has encountered one or more parallel region
// 1 bit (IsParConstr) if ICV for a parallel region (false = explicit task)
// 1 bit (InParL2+) if this thread has encountered L2 or higher parallel
// region
static const uint8_t TaskDescr_SchedMask = (0x1 | 0x2 | 0x4);
static const uint8_t TaskDescr_IsDynamic = 0x8;
static const uint8_t TaskDescr_InPar = 0x10;
static const uint8_t TaskDescr_IsParConstr = 0x20;
static const uint8_t TaskDescr_InParL2P = 0x40;
@@ -219,10 +189,7 @@ private:
struct TaskDescr_items {
uint8_t flags; // 6 bit used (see flag above)
uint8_t unused;
uint16_t nthreads; // thread num for subsequent parallel regions
uint16_t threadlimit; // thread limit ICV
uint16_t threadId; // thread id
uint16_t threadsInTeam; // threads in current team
uint64_t runtimeChunkSize; // runtime chunk size
} items;
omptarget_nvptx_TaskDescr *prev;
@@ -242,15 +209,10 @@ class omptarget_nvptx_WorkDescr {
public:
// access to data
INLINE omptarget_nvptx_CounterGroup &CounterGroup() { return cg; }
INLINE omptarget_nvptx_TaskDescr *WorkTaskDescr() { return &masterTaskICV; }
// init
INLINE void InitWorkDescr();
private:
omptarget_nvptx_CounterGroup cg; // for barrier (no other needed)
omptarget_nvptx_TaskDescr masterTaskICV;
bool hasCancel;
};
////////////////////////////////////////////////////////////////////////////////
@@ -264,7 +226,6 @@ public:
INLINE omptarget_nvptx_WorkDescr &WorkDescr() {
return workDescrForActiveParallel;
}
INLINE omp_lock_t *CriticalLock() { return &criticalLock; }
INLINE uint64_t *getLastprivateIterBuffer() { return &lastprivateIterBuffer; }
// init
@@ -316,7 +277,6 @@ private:
levelZeroTaskDescr; // icv for team master initial thread
omptarget_nvptx_WorkDescr
workDescrForActiveParallel; // one, ONLY for the active par
omp_lock_t criticalLock;
uint64_t lastprivateIterBuffer;
__align__(16)
@@ -338,7 +298,7 @@ public:
omptarget_nvptx_TaskDescr *taskICV) {
topTaskDescr[tid] = taskICV;
}
INLINE omptarget_nvptx_TaskDescr *GetTopLevelTaskDescr(int tid);
INLINE omptarget_nvptx_TaskDescr *GetTopLevelTaskDescr(int tid) const;
// parallel
INLINE uint16_t &NumThreadsForNextParallel(int tid) {
return nextRegion.tnum[tid];
@@ -347,9 +307,6 @@ public:
INLINE uint16_t &SimdLimitForNextSimd(int tid) {
return nextRegion.slim[tid];
}
// sync
INLINE Counter &Priv(int tid) { return priv[tid]; }
INLINE void IncrementPriv(int tid, Counter val) { priv[tid] += val; }
// schedule (for dispatch)
INLINE kmp_sched_t &ScheduleType(int tid) { return schedule[tid]; }
INLINE int64_t &Chunk(int tid) { return chunk[tid]; }
@@ -360,8 +317,7 @@ public:
INLINE omptarget_nvptx_TeamDescr &TeamContext() { return teamContext; }
INLINE void InitThreadPrivateContext(int tid);
INLINE void SetSourceQueue(uint64_t Src) { SourceQueue = Src; }
INLINE uint64_t GetSourceQueue() { return SourceQueue; }
INLINE uint64_t &Cnt() { return cnt; }
private:
// team context for this team
@@ -377,8 +333,6 @@ private:
// simd limit
uint16_t slim[MAX_THREADS_PER_TEAM];
} nextRegion;
// sync
Counter priv[MAX_THREADS_PER_TEAM];
// schedule (for dispatch)
kmp_sched_t schedule[MAX_THREADS_PER_TEAM]; // remember schedule type for #for
int64_t chunk[MAX_THREADS_PER_TEAM];
@@ -386,8 +340,7 @@ private:
// state for dispatch with dyn/guided OR static (never use both at a time)
int64_t nextLowerBound[MAX_THREADS_PER_TEAM];
int64_t stride[MAX_THREADS_PER_TEAM];
// Queue to which this object must be returned.
uint64_t SourceQueue;
uint64_t cnt;
};
/// Device envrionment data
@@ -395,6 +348,22 @@ struct omptarget_device_environmentTy {
int32_t debug_level;
};
/// Memory manager for statically allocated memory.
class omptarget_nvptx_SimpleMemoryManager {
private:
__align__(128) struct MemDataTy {
volatile unsigned keys[OMP_STATE_COUNT];
} MemData[MAX_SM];
INLINE static uint32_t hash(unsigned key) {
return key & (OMP_STATE_COUNT - 1);
}
public:
INLINE void Release();
INLINE const void *Acquire(const void *buf, size_t size);
};
////////////////////////////////////////////////////////////////////////////////
// global device envrionment
////////////////////////////////////////////////////////////////////////////////
@@ -407,8 +376,18 @@ extern __device__ omptarget_device_environmentTy omptarget_device_environment;
// global data tables
////////////////////////////////////////////////////////////////////////////////
extern __device__ omptarget_nvptx_SimpleMemoryManager
omptarget_nvptx_simpleMemoryManager;
extern __device__ __shared__ uint32_t usedMemIdx;
extern __device__ __shared__ uint32_t usedSlotIdx;
extern __device__ __shared__ uint8_t
parallelLevel[MAX_THREADS_PER_TEAM / WARPSIZE];
extern __device__ __shared__ uint16_t threadLimit;
extern __device__ __shared__ uint16_t threadsInTeam;
extern __device__ __shared__ uint16_t nThreads;
extern __device__ __shared__
omptarget_nvptx_ThreadPrivateContext *omptarget_nvptx_threadPrivateContext;
extern __device__ __shared__ uint32_t execution_param;
extern __device__ __shared__ void *ReductionScratchpadPtr;
@@ -427,14 +406,14 @@ extern volatile __device__ __shared__ omptarget_nvptx_WorkFn
INLINE omptarget_nvptx_TeamDescr &getMyTeamDescriptor();
INLINE omptarget_nvptx_WorkDescr &getMyWorkDescriptor();
INLINE omptarget_nvptx_TaskDescr *getMyTopTaskDescriptor();
INLINE omptarget_nvptx_TaskDescr *
getMyTopTaskDescriptor(bool isSPMDExecutionMode);
INLINE omptarget_nvptx_TaskDescr *getMyTopTaskDescriptor(int globalThreadId);
////////////////////////////////////////////////////////////////////////////////
// inlined implementation
////////////////////////////////////////////////////////////////////////////////
#include "counter_groupi.h"
#include "omptarget-nvptxi.h"
#include "supporti.h"
@@ -1,9 +1,8 @@
//===---- omptarget-nvptxi.h - NVPTX OpenMP GPU initialization --- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -16,7 +15,7 @@
// Task Descriptor
////////////////////////////////////////////////////////////////////////////////
INLINE omp_sched_t omptarget_nvptx_TaskDescr::GetRuntimeSched() {
INLINE omp_sched_t omptarget_nvptx_TaskDescr::GetRuntimeSched() const {
// sched starts from 1..4; encode it as 0..3; so add 1 here
uint8_t rc = (items.flags & TaskDescr_SchedMask) + 1;
return (omp_sched_t)rc;
@@ -31,7 +30,8 @@ INLINE void omptarget_nvptx_TaskDescr::SetRuntimeSched(omp_sched_t sched) {
items.flags |= val;
}
INLINE void omptarget_nvptx_TaskDescr::InitLevelZeroTaskDescr() {
INLINE void
omptarget_nvptx_TaskDescr::InitLevelZeroTaskDescr() {
// slow method
// flag:
// default sched is static,
@@ -39,17 +39,14 @@ INLINE void omptarget_nvptx_TaskDescr::InitLevelZeroTaskDescr() {
// not in parallel
items.flags = 0;
items.nthreads = GetNumberOfProcsInTeam();
; // threads: whatever was alloc by kernel
items.threadId = 0; // is master
items.threadsInTeam = 1; // sequential
items.runtimeChunkSize = 1; // prefered chunking statik with chunk 1
}
// This is called when all threads are started together in SPMD mode.
// OMP directives include target parallel, target distribute parallel for, etc.
INLINE void omptarget_nvptx_TaskDescr::InitLevelOneTaskDescr(
uint16_t tnum, omptarget_nvptx_TaskDescr *parentTaskDescr) {
omptarget_nvptx_TaskDescr *parentTaskDescr) {
// slow method
// flag:
// default sched is static,
@@ -58,10 +55,8 @@ INLINE void omptarget_nvptx_TaskDescr::InitLevelOneTaskDescr(
items.flags =
TaskDescr_InPar | TaskDescr_IsParConstr; // set flag to parallel
items.nthreads = 0; // # threads for subsequent parallel region
items.threadId =
GetThreadIdInBlock(); // get ids from cuda (only called for 1st level)
items.threadsInTeam = tnum;
items.runtimeChunkSize = 1; // prefered chunking statik with chunk 1
prev = parentTaskDescr;
}
@@ -91,12 +86,11 @@ INLINE void omptarget_nvptx_TaskDescr::CopyForExplicitTask(
}
INLINE void omptarget_nvptx_TaskDescr::CopyToWorkDescr(
omptarget_nvptx_TaskDescr *masterTaskDescr, uint16_t tnum) {
omptarget_nvptx_TaskDescr *masterTaskDescr) {
CopyParent(masterTaskDescr);
// overrwrite specific items;
items.flags |=
TaskDescr_InPar | TaskDescr_IsParConstr; // set flag to parallel
items.threadsInTeam = tnum; // set number of threads
}
INLINE void omptarget_nvptx_TaskDescr::CopyFromWorkDescr(
@@ -121,7 +115,6 @@ INLINE void omptarget_nvptx_TaskDescr::CopyConvergentParent(
omptarget_nvptx_TaskDescr *parentTaskDescr, uint16_t tid, uint16_t tnum) {
CopyParent(parentTaskDescr);
items.flags |= TaskDescr_InParL2P; // In L2+ parallelism
items.threadsInTeam = tnum; // set number of threads
items.threadId = tid;
}
@@ -154,7 +147,7 @@ INLINE void omptarget_nvptx_TaskDescr::RestoreLoopData() const {
////////////////////////////////////////////////////////////////////////////////
INLINE omptarget_nvptx_TaskDescr *
omptarget_nvptx_ThreadPrivateContext::GetTopLevelTaskDescr(int tid) {
omptarget_nvptx_ThreadPrivateContext::GetTopLevelTaskDescr(int tid) const {
ASSERT0(
LT_FUSSY, tid < MAX_THREADS_PER_TEAM,
"Getting top level, tid is larger than allocated data structure size");
@@ -168,31 +161,17 @@ omptarget_nvptx_ThreadPrivateContext::InitThreadPrivateContext(int tid) {
topTaskDescr[tid] = NULL;
// no num threads value has been pushed
nextRegion.tnum[tid] = 0;
// priv counter init to zero
priv[tid] = 0;
// the following don't need to be init here; they are init when using dyn
// sched
// current_Event, events_Number, chunk, num_Iterations, schedule
}
////////////////////////////////////////////////////////////////////////////////
// Work Descriptor
////////////////////////////////////////////////////////////////////////////////
INLINE void omptarget_nvptx_WorkDescr::InitWorkDescr() {
cg.Clear(); // start and stop to zero too
// threadsInParallelTeam does not need to be init (done in start parallel)
hasCancel = FALSE;
}
////////////////////////////////////////////////////////////////////////////////
// Team Descriptor
////////////////////////////////////////////////////////////////////////////////
INLINE void omptarget_nvptx_TeamDescr::InitTeamDescr() {
levelZeroTaskDescr.InitLevelZeroTaskDescr();
workDescrForActiveParallel.InitWorkDescr();
// omp_init_lock(criticalLock);
}
////////////////////////////////////////////////////////////////////////////////
@@ -213,6 +192,35 @@ INLINE omptarget_nvptx_TaskDescr *getMyTopTaskDescriptor(int threadId) {
return omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(threadId);
}
INLINE omptarget_nvptx_TaskDescr *getMyTopTaskDescriptor() {
return getMyTopTaskDescriptor(GetLogicalThreadIdInBlock());
INLINE omptarget_nvptx_TaskDescr *
getMyTopTaskDescriptor(bool isSPMDExecutionMode) {
return getMyTopTaskDescriptor(GetLogicalThreadIdInBlock(isSPMDExecutionMode));
}
////////////////////////////////////////////////////////////////////////////////
// Memory management runtime functions.
////////////////////////////////////////////////////////////////////////////////
INLINE void omptarget_nvptx_SimpleMemoryManager::Release() {
ASSERT0(LT_FUSSY, usedSlotIdx < MAX_SM,
"SlotIdx is too big or uninitialized.");
ASSERT0(LT_FUSSY, usedMemIdx < OMP_STATE_COUNT,
"MemIdx is too big or uninitialized.");
MemDataTy &MD = MemData[usedSlotIdx];
atomicExch((unsigned *)&MD.keys[usedMemIdx], 0);
}
INLINE const void *omptarget_nvptx_SimpleMemoryManager::Acquire(const void *buf,
size_t size) {
ASSERT0(LT_FUSSY, usedSlotIdx < MAX_SM,
"SlotIdx is too big or uninitialized.");
const unsigned sm = usedSlotIdx;
MemDataTy &MD = MemData[sm];
unsigned i = hash(GetBlockIdInKernel());
while (atomicCAS((unsigned *)&MD.keys[i], 0, 1) != 0) {
i = hash(i + 1);
}
usedSlotIdx = sm;
usedMemIdx = i;
return static_cast<const char *>(buf) + (sm * OMP_STATE_COUNT + i) * size;
}
+12 -14
View File
@@ -1,9 +1,8 @@
//===------------ option.h - NVPTX OpenMP GPU options ------------ CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -13,6 +12,8 @@
#ifndef _OPTION_H_
#define _OPTION_H_
#include "interface.h"
////////////////////////////////////////////////////////////////////////////////
// Kernel options
////////////////////////////////////////////////////////////////////////////////
@@ -34,7 +35,10 @@
// Maximum number of omp state objects per SM allocated statically in global
// memory.
#if __CUDA_ARCH__ >= 600
#if __CUDA_ARCH__ >= 700
#define OMP_STATE_COUNT 32
#define MAX_SM 84
#elif __CUDA_ARCH__ >= 600
#define OMP_STATE_COUNT 32
#define MAX_SM 56
#else
@@ -42,23 +46,17 @@
#define MAX_SM 16
#endif
#define OMP_ACTIVE_PARALLEL_LEVEL 128
////////////////////////////////////////////////////////////////////////////////
// algo options
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// data options
////////////////////////////////////////////////////////////////////////////////
// decide if counters are 32 or 64 bit
#define Counter unsigned long long
////////////////////////////////////////////////////////////////////////////////
// misc options (by def everythig here is device)
////////////////////////////////////////////////////////////////////////////////
#define EXTERN extern "C" __device__
#define INLINE __inline__ __device__
#define INLINE __forceinline__ __device__
#define NOINLINE __noinline__ __device__
#ifndef TRUE
#define TRUE 1
+143 -152
View File
@@ -1,9 +1,8 @@
//===---- parallel.cu - NVPTX OpenMP parallel implementation ----- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -34,6 +33,7 @@
//===----------------------------------------------------------------------===//
#include "omptarget-nvptx.h"
#include "target_impl.h"
typedef struct ConvergentSimdJob {
omptarget_nvptx_TaskDescr taskDescr;
@@ -44,20 +44,20 @@ typedef struct ConvergentSimdJob {
////////////////////////////////////////////////////////////////////////////////
// support for convergent simd (team of threads in a warp only)
////////////////////////////////////////////////////////////////////////////////
EXTERN bool __kmpc_kernel_convergent_simd(void *buffer, uint32_t Mask,
EXTERN bool __kmpc_kernel_convergent_simd(void *buffer,
__kmpc_impl_lanemask_t Mask,
bool *IsFinal, int32_t *LaneSource,
int32_t *LaneId, int32_t *NumLanes) {
PRINT0(LD_IO, "call to __kmpc_kernel_convergent_simd\n");
uint32_t ConvergentMask = Mask;
int32_t ConvergentSize = __popc(ConvergentMask);
uint32_t WorkRemaining = ConvergentMask >> (*LaneSource + 1);
*LaneSource += __ffs(WorkRemaining);
*IsFinal = __popc(WorkRemaining) == 1;
uint32_t lanemask_lt;
asm("mov.u32 %0, %%lanemask_lt;" : "=r"(lanemask_lt));
*LaneId = __popc(ConvergentMask & lanemask_lt);
__kmpc_impl_lanemask_t ConvergentMask = Mask;
int32_t ConvergentSize = __kmpc_impl_popc(ConvergentMask);
__kmpc_impl_lanemask_t WorkRemaining = ConvergentMask >> (*LaneSource + 1);
*LaneSource += __kmpc_impl_ffs(WorkRemaining);
*IsFinal = __kmpc_impl_popc(WorkRemaining) == 1;
__kmpc_impl_lanemask_t lanemask_lt = __kmpc_impl_lanemask_lt();
*LaneId = __kmpc_impl_popc(ConvergentMask & lanemask_lt);
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(isSPMDMode());
int sourceThreadId = (threadId & ~(WARPSIZE - 1)) + *LaneSource;
ConvergentSimdJob *job = (ConvergentSimdJob *)buffer;
@@ -65,7 +65,7 @@ EXTERN bool __kmpc_kernel_convergent_simd(void *buffer, uint32_t Mask,
omptarget_nvptx_threadPrivateContext->SimdLimitForNextSimd(threadId);
job->slimForNextSimd = SimdLimit;
int32_t SimdLimitSource = __SHFL_SYNC(Mask, SimdLimit, *LaneSource);
int32_t SimdLimitSource = __kmpc_impl_shfl_sync(Mask, SimdLimit, *LaneSource);
// reset simdlimit to avoid propagating to successive #simd
if (SimdLimitSource > 0 && threadId == sourceThreadId)
omptarget_nvptx_threadPrivateContext->SimdLimitForNextSimd(threadId) = 0;
@@ -76,7 +76,7 @@ EXTERN bool __kmpc_kernel_convergent_simd(void *buffer, uint32_t Mask,
else
*NumLanes = ConvergentSize;
ASSERT(LT_FUSSY, *NumLanes > 0, "bad thread request of %d threads",
*NumLanes);
(int)*NumLanes);
// Set to true for lanes participating in the simd region.
bool isActive = false;
@@ -101,7 +101,7 @@ EXTERN bool __kmpc_kernel_convergent_simd(void *buffer, uint32_t Mask,
EXTERN void __kmpc_kernel_end_convergent_simd(void *buffer) {
PRINT0(LD_IO | LD_PAR, "call to __kmpc_kernel_end_convergent_parallel\n");
// pop stack
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(isSPMDMode());
ConvergentSimdJob *job = (ConvergentSimdJob *)buffer;
omptarget_nvptx_threadPrivateContext->SimdLimitForNextSimd(threadId) =
job->slimForNextSimd;
@@ -118,20 +118,20 @@ typedef struct ConvergentParallelJob {
////////////////////////////////////////////////////////////////////////////////
// support for convergent parallelism (team of threads in a warp only)
////////////////////////////////////////////////////////////////////////////////
EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer, uint32_t Mask,
EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer,
__kmpc_impl_lanemask_t Mask,
bool *IsFinal,
int32_t *LaneSource) {
PRINT0(LD_IO, "call to __kmpc_kernel_convergent_parallel\n");
uint32_t ConvergentMask = Mask;
int32_t ConvergentSize = __popc(ConvergentMask);
uint32_t WorkRemaining = ConvergentMask >> (*LaneSource + 1);
*LaneSource += __ffs(WorkRemaining);
*IsFinal = __popc(WorkRemaining) == 1;
uint32_t lanemask_lt;
asm("mov.u32 %0, %%lanemask_lt;" : "=r"(lanemask_lt));
uint32_t OmpId = __popc(ConvergentMask & lanemask_lt);
__kmpc_impl_lanemask_t ConvergentMask = Mask;
int32_t ConvergentSize = __kmpc_impl_popc(ConvergentMask);
__kmpc_impl_lanemask_t WorkRemaining = ConvergentMask >> (*LaneSource + 1);
*LaneSource += __kmpc_impl_ffs(WorkRemaining);
*IsFinal = __kmpc_impl_popc(WorkRemaining) == 1;
__kmpc_impl_lanemask_t lanemask_lt = __kmpc_impl_lanemask_lt();
uint32_t OmpId = __kmpc_impl_popc(ConvergentMask & lanemask_lt);
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(isSPMDMode());
int sourceThreadId = (threadId & ~(WARPSIZE - 1)) + *LaneSource;
ConvergentParallelJob *job = (ConvergentParallelJob *)buffer;
@@ -139,7 +139,8 @@ EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer, uint32_t Mask,
omptarget_nvptx_threadPrivateContext->NumThreadsForNextParallel(threadId);
job->tnumForNextPar = NumThreadsClause;
int32_t NumThreadsSource = __SHFL_SYNC(Mask, NumThreadsClause, *LaneSource);
int32_t NumThreadsSource =
__kmpc_impl_shfl_sync(Mask, NumThreadsClause, *LaneSource);
// reset numthreads to avoid propagating to successive #parallel
if (NumThreadsSource > 0 && threadId == sourceThreadId)
omptarget_nvptx_threadPrivateContext->NumThreadsForNextParallel(threadId) =
@@ -152,7 +153,7 @@ EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer, uint32_t Mask,
else
NumThreads = ConvergentSize;
ASSERT(LT_FUSSY, NumThreads > 0, "bad thread request of %d threads",
NumThreads);
(int)NumThreads);
// Set to true for workers participating in the parallel region.
bool isActive = false;
@@ -181,7 +182,7 @@ EXTERN bool __kmpc_kernel_convergent_parallel(void *buffer, uint32_t Mask,
EXTERN void __kmpc_kernel_end_convergent_parallel(void *buffer) {
PRINT0(LD_IO | LD_PAR, "call to __kmpc_kernel_end_convergent_parallel\n");
// pop stack
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(isSPMDMode());
ConvergentParallelJob *job = (ConvergentParallelJob *)buffer;
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(
threadId, job->convHeadTaskDescr);
@@ -193,38 +194,50 @@ EXTERN void __kmpc_kernel_end_convergent_parallel(void *buffer) {
// support for parallel that goes parallel (1 static level only)
////////////////////////////////////////////////////////////////////////////////
// return number of cuda threads that participate to parallel
// calculation has to consider simd implementation in nvptx
// i.e. (num omp threads * num lanes)
//
// cudathreads =
// if(num_threads != 0) {
// if(thread_limit > 0) {
// min (num_threads*numLanes ; thread_limit*numLanes);
// } else {
// min (num_threads*numLanes; blockDim.x)
// }
// } else {
// if (thread_limit != 0) {
// min (thread_limit*numLanes; blockDim.x)
// } else { // no thread_limit, no num_threads, use all cuda threads
// blockDim.x;
// }
// }
//
INLINE static uint16_t determineNumberOfThreads(uint16_t NumThreadsClause,
uint16_t NThreadsICV,
uint16_t ThreadLimit) {
uint16_t ThreadsRequested = NThreadsICV;
if (NumThreadsClause != 0) {
ThreadsRequested = NumThreadsClause;
}
uint16_t ThreadsAvailable = GetNumberOfWorkersInTeam();
if (ThreadLimit != 0 && ThreadLimit < ThreadsAvailable) {
ThreadsAvailable = ThreadLimit;
}
uint16_t NumThreads = ThreadsAvailable;
if (ThreadsRequested != 0 && ThreadsRequested < NumThreads) {
NumThreads = ThreadsRequested;
}
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
// On Volta and newer architectures we require that all lanes in
// a warp participate in the parallel region. Round down to a
// multiple of WARPSIZE since it is legal to do so in OpenMP.
if (NumThreads < WARPSIZE) {
NumThreads = 1;
} else {
NumThreads = (NumThreads & ~((uint16_t)WARPSIZE - 1));
}
#endif
return NumThreads;
}
// This routine is always called by the team master..
EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn,
int16_t IsOMPRuntimeInitialized) {
PRINT0(LD_IO, "call to __kmpc_kernel_prepare_parallel\n");
omptarget_nvptx_workFn = WorkFn;
ASSERT0(LT_FUSSY, IsOMPRuntimeInitialized, "Expected initialized runtime.");
if (!IsOMPRuntimeInitialized)
return;
omptarget_nvptx_workFn = WorkFn;
// This routine is only called by the team master. The team master is
// the first thread of the last warp. It always has the logical thread
// id of 0 (since it is a shadow for the first worker thread).
int threadId = 0;
const int threadId = 0;
omptarget_nvptx_TaskDescr *currTaskDescr =
omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(threadId);
ASSERT0(LT_FUSSY, currTaskDescr, "expected a top task descr");
@@ -235,80 +248,26 @@ EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn,
return;
}
uint16_t CudaThreadsForParallel = 0;
uint16_t NumThreadsClause =
uint16_t &NumThreadsClause =
omptarget_nvptx_threadPrivateContext->NumThreadsForNextParallel(threadId);
// we cannot have more than block size
uint16_t CudaThreadsAvail = GetNumberOfWorkersInTeam();
uint16_t NumThreads =
determineNumberOfThreads(NumThreadsClause, nThreads, threadLimit);
// currTaskDescr->ThreadLimit(): If non-zero, this is the limit as
// specified by the thread_limit clause on the target directive.
// GetNumberOfWorkersInTeam(): This is the number of workers available
// in this kernel instance.
//
// E.g: If thread_limit is 33, the kernel is launched with 33+32=65
// threads. The last warp is the master warp so in this case
// GetNumberOfWorkersInTeam() returns 64.
// this is different from ThreadAvail of OpenMP because we may be
// using some of the CUDA threads as SIMD lanes
int NumLanes = 1;
if (NumThreadsClause != 0) {
// reset request to avoid propagating to successive #parallel
omptarget_nvptx_threadPrivateContext->NumThreadsForNextParallel(threadId) =
0;
// assume that thread_limit*numlanes is already <= CudaThreadsAvail
// because that is already checked on the host side (CUDA offloading rtl)
if (currTaskDescr->ThreadLimit() != 0)
CudaThreadsForParallel =
NumThreadsClause * NumLanes < currTaskDescr->ThreadLimit() * NumLanes
? NumThreadsClause * NumLanes
: currTaskDescr->ThreadLimit() * NumLanes;
else {
CudaThreadsForParallel = (NumThreadsClause * NumLanes > CudaThreadsAvail)
? CudaThreadsAvail
: NumThreadsClause * NumLanes;
}
} else {
if (currTaskDescr->ThreadLimit() != 0) {
CudaThreadsForParallel =
(currTaskDescr->ThreadLimit() * NumLanes > CudaThreadsAvail)
? CudaThreadsAvail
: currTaskDescr->ThreadLimit() * NumLanes;
} else
CudaThreadsForParallel = CudaThreadsAvail;
// Reset request to avoid propagating to successive #parallel
NumThreadsClause = 0;
}
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 700
// On Volta and newer architectures we require that all lanes in
// a warp participate in the parallel region. Round down to a
// multiple of WARPSIZE since it is legal to do so in OpenMP.
// CudaThreadsAvail is the number of workers available in this
// kernel instance and is greater than or equal to
// currTaskDescr->ThreadLimit().
if (CudaThreadsForParallel < CudaThreadsAvail) {
CudaThreadsForParallel =
(CudaThreadsForParallel < WARPSIZE)
? 1
: CudaThreadsForParallel & ~((uint16_t)WARPSIZE - 1);
}
#endif
ASSERT(LT_FUSSY, CudaThreadsForParallel > 0,
"bad thread request of %d threads", CudaThreadsForParallel);
ASSERT(LT_FUSSY, NumThreads > 0, "bad thread request of %d threads",
(int)NumThreads);
ASSERT0(LT_FUSSY, GetThreadIdInBlock() == GetMasterThreadID(),
"only team master can create parallel");
// set number of threads on work descriptor
// this is different from the number of cuda threads required for the parallel
// region
// Set number of threads on work descriptor.
omptarget_nvptx_WorkDescr &workDescr = getMyWorkDescriptor();
workDescr.WorkTaskDescr()->CopyToWorkDescr(currTaskDescr,
CudaThreadsForParallel / NumLanes);
// init counters (copy start to init)
workDescr.CounterGroup().Reset();
workDescr.WorkTaskDescr()->CopyToWorkDescr(currTaskDescr);
threadsInTeam = NumThreads;
}
// All workers call this function. Deactivate those not needed.
@@ -320,15 +279,16 @@ EXTERN bool __kmpc_kernel_parallel(void **WorkFn,
int16_t IsOMPRuntimeInitialized) {
PRINT0(LD_IO | LD_PAR, "call to __kmpc_kernel_parallel\n");
ASSERT0(LT_FUSSY, IsOMPRuntimeInitialized, "Expected initialized runtime.");
// Work function and arguments for L1 parallel region.
*WorkFn = omptarget_nvptx_workFn;
if (!IsOMPRuntimeInitialized)
return true;
// If this is the termination signal from the master, quit early.
if (!*WorkFn)
if (!*WorkFn) {
PRINT0(LD_IO | LD_PAR, "call to __kmpc_kernel_parallel finished\n");
return false;
}
// Only the worker threads call this routine and the master warp
// never arrives here. Therefore, use the nvptx thread id.
@@ -337,7 +297,7 @@ EXTERN bool __kmpc_kernel_parallel(void **WorkFn,
// Set to true for workers participating in the parallel region.
bool isActive = false;
// Initialize state for active threads.
if (threadId < workDescr.WorkTaskDescr()->ThreadsInTeam()) {
if (threadId < threadsInTeam) {
// init work descriptor from workdesccr
omptarget_nvptx_TaskDescr *newTaskDescr =
omptarget_nvptx_threadPrivateContext->Level1TaskDescr(threadId);
@@ -347,14 +307,22 @@ EXTERN bool __kmpc_kernel_parallel(void **WorkFn,
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(threadId,
newTaskDescr);
// init private from int value
workDescr.CounterGroup().Init(
omptarget_nvptx_threadPrivateContext->Priv(threadId));
PRINT(LD_PAR,
"thread will execute parallel region with id %d in a team of "
"%d threads\n",
newTaskDescr->ThreadId(), newTaskDescr->NThreads());
(int)newTaskDescr->ThreadId(), (int)nThreads);
isActive = true;
// Reconverge the threads at the end of the parallel region to correctly
// handle parallel levels.
// In Cuda9+ in non-SPMD mode we have either 1 worker thread or the whole
// warp. If only 1 thread is active, not need to reconverge the threads.
// If we have the whole warp, reconverge all the threads in the warp before
// actually trying to change the parallel level. Otherwise, parallel level
// can be changed incorrectly because of threads divergence.
bool IsActiveParallelRegion = threadsInTeam != 1;
IncParallelLevel(IsActiveParallelRegion,
IsActiveParallelRegion ? __kmpc_impl_all_lanes : 1u);
}
return isActive;
@@ -363,23 +331,44 @@ EXTERN bool __kmpc_kernel_parallel(void **WorkFn,
EXTERN void __kmpc_kernel_end_parallel() {
// pop stack
PRINT0(LD_IO | LD_PAR, "call to __kmpc_kernel_end_parallel\n");
ASSERT0(LT_FUSSY, isRuntimeInitialized(), "Expected initialized runtime.");
// Only the worker threads call this routine and the master warp
// never arrives here. Therefore, use the nvptx thread id.
int threadId = GetThreadIdInBlock();
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor(threadId);
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(
threadId, currTaskDescr->GetPrevTaskDescr());
// Reconverge the threads at the end of the parallel region to correctly
// handle parallel levels.
// In Cuda9+ in non-SPMD mode we have either 1 worker thread or the whole
// warp. If only 1 thread is active, not need to reconverge the threads.
// If we have the whole warp, reconverge all the threads in the warp before
// actually trying to change the parallel level. Otherwise, parallel level can
// be changed incorrectly because of threads divergence.
bool IsActiveParallelRegion = threadsInTeam != 1;
DecParallelLevel(IsActiveParallelRegion,
IsActiveParallelRegion ? __kmpc_impl_all_lanes : 1u);
}
////////////////////////////////////////////////////////////////////////////////
// support for parallel that goes sequential
////////////////////////////////////////////////////////////////////////////////
EXTERN void __kmpc_serialized_parallel(kmp_Indent *loc, uint32_t global_tid) {
EXTERN void __kmpc_serialized_parallel(kmp_Ident *loc, uint32_t global_tid) {
PRINT0(LD_IO, "call to __kmpc_serialized_parallel\n");
IncParallelLevel(/*ActiveParallel=*/false, __kmpc_impl_activemask());
if (checkRuntimeUninitialized(loc)) {
ASSERT0(LT_FUSSY, checkSPMDMode(loc),
"Expected SPMD mode with uninitialized runtime.");
return;
}
// assume this is only called for nested parallel
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
// unlike actual parallel, threads in the same team do not share
// the workTaskDescr in this case and num threads is fixed to 1
@@ -392,26 +381,33 @@ EXTERN void __kmpc_serialized_parallel(kmp_Indent *loc, uint32_t global_tid) {
// it
omptarget_nvptx_TaskDescr *newTaskDescr =
(omptarget_nvptx_TaskDescr *)SafeMalloc(sizeof(omptarget_nvptx_TaskDescr),
(char *)"new seq parallel task");
"new seq parallel task");
newTaskDescr->CopyParent(currTaskDescr);
// tweak values for serialized parallel case:
// - each thread becomes ID 0 in its serialized parallel, and
// - there is only one thread per team
newTaskDescr->ThreadId() = 0;
newTaskDescr->ThreadsInTeam() = 1;
// set new task descriptor as top
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(threadId,
newTaskDescr);
}
EXTERN void __kmpc_end_serialized_parallel(kmp_Indent *loc,
EXTERN void __kmpc_end_serialized_parallel(kmp_Ident *loc,
uint32_t global_tid) {
PRINT0(LD_IO, "call to __kmpc_end_serialized_parallel\n");
DecParallelLevel(/*ActiveParallel=*/false, __kmpc_impl_activemask());
if (checkRuntimeUninitialized(loc)) {
ASSERT0(LT_FUSSY, checkSPMDMode(loc),
"Expected SPMD mode with uninitialized runtime.");
return;
}
// pop stack
int threadId = GetLogicalThreadIdInBlock();
int threadId = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor(threadId);
// set new top
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(
@@ -422,58 +418,53 @@ EXTERN void __kmpc_end_serialized_parallel(kmp_Indent *loc,
currTaskDescr->RestoreLoopData();
}
EXTERN uint16_t __kmpc_parallel_level(kmp_Indent *loc, uint32_t global_tid) {
EXTERN uint16_t __kmpc_parallel_level(kmp_Ident *loc, uint32_t global_tid) {
PRINT0(LD_IO, "call to __kmpc_parallel_level\n");
int threadId = GetLogicalThreadIdInBlock();
omptarget_nvptx_TaskDescr *currTaskDescr =
omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(threadId);
if (currTaskDescr->InL2OrHigherParallelRegion())
return 2;
else if (currTaskDescr->InParallelRegion())
return 1;
else
return 0;
return parallelLevel[GetWarpId()] & (OMP_ACTIVE_PARALLEL_LEVEL - 1);
}
// This kmpc call returns the thread id across all teams. It's value is
// cached by the compiler and used when calling the runtime. On nvptx
// it's cheap to recalculate this value so we never use the result
// of this call.
EXTERN int32_t __kmpc_global_thread_num(kmp_Indent *loc) {
return GetLogicalThreadIdInBlock();
EXTERN int32_t __kmpc_global_thread_num(kmp_Ident *loc) {
int tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
return GetOmpThreadId(tid, checkSPMDMode(loc));
}
////////////////////////////////////////////////////////////////////////////////
// push params
////////////////////////////////////////////////////////////////////////////////
EXTERN void __kmpc_push_num_threads(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_push_num_threads(kmp_Ident *loc, int32_t tid,
int32_t num_threads) {
PRINT(LD_IO, "call kmpc_push_num_threads %d\n", num_threads);
tid = GetLogicalThreadIdInBlock();
ASSERT0(LT_FUSSY, checkRuntimeInitialized(loc), "Runtime must be initialized.");
tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_threadPrivateContext->NumThreadsForNextParallel(tid) =
num_threads;
}
EXTERN void __kmpc_push_simd_limit(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_push_simd_limit(kmp_Ident *loc, int32_t tid,
int32_t simd_limit) {
PRINT(LD_IO, "call kmpc_push_simd_limit %d\n", simd_limit);
tid = GetLogicalThreadIdInBlock();
PRINT(LD_IO, "call kmpc_push_simd_limit %d\n", (int)simd_limit);
ASSERT0(LT_FUSSY, checkRuntimeInitialized(loc), "Runtime must be initialized.");
tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_threadPrivateContext->SimdLimitForNextSimd(tid) = simd_limit;
}
// Do nothing. The host guarantees we started the requested number of
// teams and we only need inspection of gridDim.
EXTERN void __kmpc_push_num_teams(kmp_Indent *loc, int32_t tid,
EXTERN void __kmpc_push_num_teams(kmp_Ident *loc, int32_t tid,
int32_t num_teams, int32_t thread_limit) {
PRINT(LD_IO, "call kmpc_push_num_teams %d\n", num_teams);
PRINT(LD_IO, "call kmpc_push_num_teams %d\n", (int)num_teams);
ASSERT0(LT_FUSSY, FALSE,
"should never have anything with new teams on device");
}
EXTERN void __kmpc_push_proc_bind(kmp_Indent *loc, uint32_t tid,
EXTERN void __kmpc_push_proc_bind(kmp_Ident *loc, uint32_t tid,
int proc_bind) {
PRINT(LD_IO, "call kmpc_push_proc_bind %d\n", proc_bind);
PRINT(LD_IO, "call kmpc_push_proc_bind %d\n", (int)proc_bind);
}
+224 -119
View File
@@ -1,10 +1,9 @@
//===---- reduction.cu - NVPTX OpenMP reduction implementation ---- CUDA
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -16,53 +15,7 @@
#include <stdio.h>
#include "omptarget-nvptx.h"
// may eventually remove this
EXTERN
int32_t __gpu_block_reduce() {
int tid = GetLogicalThreadIdInBlock();
int nt = GetNumberOfOmpThreads(tid, isSPMDMode(), isRuntimeUninitialized());
if (nt != blockDim.x)
return 0;
unsigned tnum = __ACTIVEMASK();
if (tnum != (~0x0)) // assume swapSize is 32
return 0;
return 1;
}
EXTERN
int32_t __kmpc_reduce_gpu(kmp_Indent *loc, int32_t global_tid, int32_t num_vars,
size_t reduce_size, void *reduce_data,
void *reduce_array_size, kmp_ReductFctPtr *reductFct,
kmp_CriticalName *lck) {
int threadId = GetLogicalThreadIdInBlock();
omptarget_nvptx_TaskDescr *currTaskDescr = getMyTopTaskDescriptor(threadId);
int numthread;
if (currTaskDescr->IsParallelConstruct()) {
numthread =
GetNumberOfOmpThreads(threadId, isSPMDMode(), isRuntimeUninitialized());
} else {
numthread = GetNumberOfOmpTeams();
}
if (numthread == 1)
return 1;
if (!__gpu_block_reduce())
return 2;
if (threadIdx.x == 0)
return 1;
return 0;
}
EXTERN
int32_t __kmpc_reduce_combined(kmp_Indent *loc) {
return threadIdx.x == 0 ? 2 : 0;
}
EXTERN
int32_t __kmpc_reduce_simd(kmp_Indent *loc) {
return (threadIdx.x % 32 == 0) ? 1 : 0;
}
#include "target_impl.h"
EXTERN
void __kmpc_nvptx_end_reduce(int32_t global_tid) {}
@@ -71,19 +24,18 @@ EXTERN
void __kmpc_nvptx_end_reduce_nowait(int32_t global_tid) {}
EXTERN int32_t __kmpc_shuffle_int32(int32_t val, int16_t delta, int16_t size) {
return __SHFL_DOWN_SYNC(0xFFFFFFFF, val, delta, size);
return __kmpc_impl_shfl_down_sync(__kmpc_impl_all_lanes, val, delta, size);
}
EXTERN int64_t __kmpc_shuffle_int64(int64_t val, int16_t delta, int16_t size) {
int lo, hi;
asm volatile("mov.b64 {%0,%1}, %2;" : "=r"(lo), "=r"(hi) : "l"(val));
hi = __SHFL_DOWN_SYNC(0xFFFFFFFF, hi, delta, size);
lo = __SHFL_DOWN_SYNC(0xFFFFFFFF, lo, delta, size);
asm volatile("mov.b64 %0, {%1,%2};" : "=l"(val) : "r"(lo), "r"(hi));
return val;
uint32_t lo, hi;
__kmpc_impl_unpack(val, lo, hi);
hi = __kmpc_impl_shfl_down_sync(__kmpc_impl_all_lanes, hi, delta, size);
lo = __kmpc_impl_shfl_down_sync(__kmpc_impl_all_lanes, lo, delta, size);
return __kmpc_impl_pack(lo, hi);
}
static INLINE void gpu_regular_warp_reduce(void *reduce_data,
INLINE static void gpu_regular_warp_reduce(void *reduce_data,
kmp_ShuffleReductFctPtr shflFct) {
for (uint32_t mask = WARPSIZE / 2; mask > 0; mask /= 2) {
shflFct(reduce_data, /*LaneId - not used= */ 0,
@@ -91,7 +43,7 @@ static INLINE void gpu_regular_warp_reduce(void *reduce_data,
}
}
static INLINE void gpu_irregular_warp_reduce(void *reduce_data,
INLINE static void gpu_irregular_warp_reduce(void *reduce_data,
kmp_ShuffleReductFctPtr shflFct,
uint32_t size, uint32_t tid) {
uint32_t curr_size;
@@ -105,20 +57,18 @@ static INLINE void gpu_irregular_warp_reduce(void *reduce_data,
}
}
static INLINE uint32_t
INLINE static uint32_t
gpu_irregular_simd_reduce(void *reduce_data, kmp_ShuffleReductFctPtr shflFct) {
uint32_t lanemask_lt;
uint32_t lanemask_gt;
uint32_t size, remote_id, physical_lane_id;
physical_lane_id = GetThreadIdInBlock() % WARPSIZE;
asm("mov.u32 %0, %%lanemask_lt;" : "=r"(lanemask_lt));
uint32_t Liveness = __BALLOT_SYNC(0xFFFFFFFF, true);
uint32_t logical_lane_id = __popc(Liveness & lanemask_lt) * 2;
asm("mov.u32 %0, %%lanemask_gt;" : "=r"(lanemask_gt));
__kmpc_impl_lanemask_t lanemask_lt = __kmpc_impl_lanemask_lt();
__kmpc_impl_lanemask_t Liveness = __kmpc_impl_activemask();
uint32_t logical_lane_id = __kmpc_impl_popc(Liveness & lanemask_lt) * 2;
__kmpc_impl_lanemask_t lanemask_gt = __kmpc_impl_lanemask_gt();
do {
Liveness = __BALLOT_SYNC(0xFFFFFFFF, true);
remote_id = __ffs(Liveness & lanemask_gt);
size = __popc(Liveness);
Liveness = __kmpc_impl_activemask();
remote_id = __kmpc_impl_ffs(Liveness & lanemask_gt);
size = __kmpc_impl_popc(Liveness);
logical_lane_id /= 2;
shflFct(reduce_data, /*LaneId =*/logical_lane_id,
/*Offset=*/remote_id - 1 - physical_lane_id, /*AlgoVersion=*/2);
@@ -131,8 +81,8 @@ int32_t __kmpc_nvptx_simd_reduce_nowait(int32_t global_tid, int32_t num_vars,
size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct) {
uint32_t Liveness = __BALLOT_SYNC(0xFFFFFFFF, true);
if (Liveness == 0xffffffff) {
__kmpc_impl_lanemask_t Liveness = __kmpc_impl_activemask();
if (Liveness == __kmpc_impl_all_lanes) {
gpu_regular_warp_reduce(reduce_data, shflFct);
return GetThreadIdInBlock() % WARPSIZE ==
0; // Result on lane 0 of the simd warp.
@@ -143,15 +93,12 @@ int32_t __kmpc_nvptx_simd_reduce_nowait(int32_t global_tid, int32_t num_vars,
}
INLINE
int32_t nvptx_parallel_reduce_nowait(int32_t global_tid, int32_t num_vars,
size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct,
bool isSPMDExecutionMode,
bool isRuntimeUninitialized = false) {
uint32_t BlockThreadId = GetLogicalThreadIdInBlock();
uint32_t NumThreads = GetNumberOfOmpThreads(
BlockThreadId, isSPMDExecutionMode, isRuntimeUninitialized);
static int32_t nvptx_parallel_reduce_nowait(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct,
bool isSPMDExecutionMode, bool isRuntimeUninitialized) {
uint32_t BlockThreadId = GetLogicalThreadIdInBlock(isSPMDExecutionMode);
uint32_t NumThreads = GetNumberOfOmpThreads(isSPMDExecutionMode);
if (NumThreads == 1)
return 1;
/*
@@ -192,17 +139,15 @@ int32_t nvptx_parallel_reduce_nowait(int32_t global_tid, int32_t num_vars,
if (WarpId == 0)
gpu_irregular_warp_reduce(reduce_data, shflFct, WarpsNeeded,
BlockThreadId);
return BlockThreadId == 0;
}
return BlockThreadId == 0;
#else
uint32_t Liveness = __BALLOT_SYNC(0xFFFFFFFF, true);
if (Liveness == 0xffffffff) // Full warp
__kmpc_impl_lanemask_t Liveness = __kmpc_impl_activemask();
if (Liveness == __kmpc_impl_all_lanes) // Full warp
gpu_regular_warp_reduce(reduce_data, shflFct);
else if (!(Liveness & (Liveness + 1))) // Partial warp but contiguous lanes
gpu_irregular_warp_reduce(reduce_data, shflFct,
/*LaneCount=*/__popc(Liveness),
/*LaneCount=*/__kmpc_impl_popc(Liveness),
/*LaneId=*/GetThreadIdInBlock() % WARPSIZE);
else if (!isRuntimeUninitialized) // Dispersed lanes. Only threads in L2
// parallel region may enter here; return
@@ -231,55 +176,61 @@ int32_t nvptx_parallel_reduce_nowait(int32_t global_tid, int32_t num_vars,
// Get the OMP thread Id. This is different from BlockThreadId in the case of
// an L2 parallel region.
return GetOmpThreadId(BlockThreadId, isSPMDExecutionMode,
isRuntimeUninitialized) == 0;
return global_tid == 0;
#endif // __CUDA_ARCH__ >= 700
}
EXTERN
int32_t __kmpc_nvptx_parallel_reduce_nowait(
EXTERN __attribute__((deprecated)) int32_t __kmpc_nvptx_parallel_reduce_nowait(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct) {
return nvptx_parallel_reduce_nowait(global_tid, num_vars, reduce_size,
reduce_data, shflFct, cpyFct,
/*isSPMDExecutionMode=*/isSPMDMode());
isSPMDMode(), isRuntimeUninitialized());
}
EXTERN
int32_t __kmpc_nvptx_parallel_reduce_nowait_v2(
kmp_Ident *loc, int32_t global_tid, int32_t num_vars, size_t reduce_size,
void *reduce_data, kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct) {
return nvptx_parallel_reduce_nowait(
global_tid, num_vars, reduce_size, reduce_data, shflFct, cpyFct,
checkSPMDMode(loc), checkRuntimeUninitialized(loc));
}
EXTERN
int32_t __kmpc_nvptx_parallel_reduce_nowait_simple_spmd(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct) {
return nvptx_parallel_reduce_nowait(global_tid, num_vars, reduce_size,
reduce_data, shflFct, cpyFct,
/*isSPMDExecutionMode=*/true,
/*isRuntimeUninitialized=*/true);
return nvptx_parallel_reduce_nowait(
global_tid, num_vars, reduce_size, reduce_data, shflFct, cpyFct,
/*isSPMDExecutionMode=*/true, /*isRuntimeUninitialized=*/true);
}
EXTERN
int32_t __kmpc_nvptx_parallel_reduce_nowait_simple_generic(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct) {
return nvptx_parallel_reduce_nowait(global_tid, num_vars, reduce_size,
reduce_data, shflFct, cpyFct,
/*isSPMDExecutionMode=*/false,
/*isRuntimeUninitialized=*/true);
return nvptx_parallel_reduce_nowait(
global_tid, num_vars, reduce_size, reduce_data, shflFct, cpyFct,
/*isSPMDExecutionMode=*/false, /*isRuntimeUninitialized=*/true);
}
INLINE
int32_t nvptx_teams_reduce_nowait(
int32_t global_tid, int32_t num_vars, size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct, kmp_InterWarpCopyFctPtr cpyFct,
kmp_CopyToScratchpadFctPtr scratchFct, kmp_LoadReduceFctPtr ldFct,
bool isSPMDExecutionMode, bool isRuntimeUninitialized = false) {
uint32_t ThreadId = GetLogicalThreadIdInBlock();
static int32_t nvptx_teams_reduce_nowait(int32_t global_tid, int32_t num_vars,
size_t reduce_size, void *reduce_data,
kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct,
kmp_CopyToScratchpadFctPtr scratchFct,
kmp_LoadReduceFctPtr ldFct,
bool isSPMDExecutionMode) {
uint32_t ThreadId = GetLogicalThreadIdInBlock(isSPMDExecutionMode);
// In non-generic mode all workers participate in the teams reduction.
// In generic mode only the team master participates in the teams
// reduction because the workers are waiting for parallel work.
uint32_t NumThreads =
isSPMDExecutionMode
? GetNumberOfOmpThreads(ThreadId, /*isSPMDExecutionMode=*/true,
isRuntimeUninitialized)
: /*Master thread only*/ 1;
isSPMDExecutionMode ? GetNumberOfOmpThreads(/*isSPMDExecutionMode=*/true)
: /*Master thread only*/ 1;
uint32_t TeamId = GetBlockIdInKernel();
uint32_t NumTeams = GetNumberOfBlocksInKernel();
__shared__ volatile bool IsLastTeam;
@@ -366,12 +317,12 @@ int32_t nvptx_teams_reduce_nowait(
ldFct(reduce_data, scratchpad, i, NumTeams, /*Load and reduce*/ 1);
// Reduce across warps to the warp master.
uint32_t Liveness = __BALLOT_SYNC(0xFFFFFFFF, true);
if (Liveness == 0xffffffff) // Full warp
__kmpc_impl_lanemask_t Liveness = __kmpc_impl_activemask();
if (Liveness == __kmpc_impl_all_lanes) // Full warp
gpu_regular_warp_reduce(reduce_data, shflFct);
else // Partial warp but contiguous lanes
gpu_irregular_warp_reduce(reduce_data, shflFct,
/*LaneCount=*/__popc(Liveness),
/*LaneCount=*/__kmpc_impl_popc(Liveness),
/*LaneId=*/ThreadId % WARPSIZE);
// When we have more than [warpsize] number of threads
@@ -401,7 +352,7 @@ int32_t __kmpc_nvptx_teams_reduce_nowait(int32_t global_tid, int32_t num_vars,
kmp_LoadReduceFctPtr ldFct) {
return nvptx_teams_reduce_nowait(global_tid, num_vars, reduce_size,
reduce_data, shflFct, cpyFct, scratchFct,
ldFct, /*isSPMDExecutionMode=*/isSPMDMode());
ldFct, isSPMDMode());
}
EXTERN
@@ -411,9 +362,7 @@ int32_t __kmpc_nvptx_teams_reduce_nowait_simple_spmd(
kmp_CopyToScratchpadFctPtr scratchFct, kmp_LoadReduceFctPtr ldFct) {
return nvptx_teams_reduce_nowait(global_tid, num_vars, reduce_size,
reduce_data, shflFct, cpyFct, scratchFct,
ldFct,
/*isSPMDExecutionMode=*/true,
/*isRuntimeUninitialized=*/true);
ldFct, /*isSPMDExecutionMode=*/true);
}
EXTERN
@@ -423,7 +372,163 @@ int32_t __kmpc_nvptx_teams_reduce_nowait_simple_generic(
kmp_CopyToScratchpadFctPtr scratchFct, kmp_LoadReduceFctPtr ldFct) {
return nvptx_teams_reduce_nowait(global_tid, num_vars, reduce_size,
reduce_data, shflFct, cpyFct, scratchFct,
ldFct,
/*isSPMDExecutionMode=*/false,
/*isRuntimeUninitialized=*/true);
ldFct, /*isSPMDExecutionMode=*/false);
}
EXTERN int32_t __kmpc_nvptx_teams_reduce_nowait_simple(kmp_Ident *loc,
int32_t global_tid,
kmp_CriticalName *crit) {
if (checkSPMDMode(loc) && GetThreadIdInBlock() != 0)
return 0;
// The master thread of the team actually does the reduction.
while (atomicCAS((uint32_t *)crit, 0, 1))
;
return 1;
}
EXTERN void
__kmpc_nvptx_teams_end_reduce_nowait_simple(kmp_Ident *loc, int32_t global_tid,
kmp_CriticalName *crit) {
__threadfence_system();
(void)atomicExch((uint32_t *)crit, 0);
}
INLINE static bool isMaster(kmp_Ident *loc, uint32_t ThreadId) {
return checkGenericMode(loc) || IsTeamMaster(ThreadId);
}
INLINE static uint32_t roundToWarpsize(uint32_t s) {
if (s < WARPSIZE)
return 1;
return (s & ~(unsigned)(WARPSIZE - 1));
}
__device__ static volatile uint32_t IterCnt = 0;
__device__ static volatile uint32_t Cnt = 0;
EXTERN int32_t __kmpc_nvptx_teams_reduce_nowait_v2(
kmp_Ident *loc, int32_t global_tid, void *global_buffer,
int32_t num_of_records, void *reduce_data, kmp_ShuffleReductFctPtr shflFct,
kmp_InterWarpCopyFctPtr cpyFct, kmp_ListGlobalFctPtr lgcpyFct,
kmp_ListGlobalFctPtr lgredFct, kmp_ListGlobalFctPtr glcpyFct,
kmp_ListGlobalFctPtr glredFct) {
// Terminate all threads in non-SPMD mode except for the master thread.
if (checkGenericMode(loc) && GetThreadIdInBlock() != GetMasterThreadID())
return 0;
uint32_t ThreadId = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
// In non-generic mode all workers participate in the teams reduction.
// In generic mode only the team master participates in the teams
// reduction because the workers are waiting for parallel work.
uint32_t NumThreads =
checkSPMDMode(loc) ? GetNumberOfOmpThreads(/*isSPMDExecutionMode=*/true)
: /*Master thread only*/ 1;
uint32_t TeamId = GetBlockIdInKernel();
uint32_t NumTeams = GetNumberOfBlocksInKernel();
__shared__ unsigned Bound;
__shared__ unsigned ChunkTeamCount;
// Block progress for teams greater than the current upper
// limit. We always only allow a number of teams less or equal
// to the number of slots in the buffer.
bool IsMaster = isMaster(loc, ThreadId);
while (IsMaster) {
// Atomic read
Bound = atomicAdd((uint32_t *)&IterCnt, 0);
if (TeamId < Bound + num_of_records)
break;
}
if (IsMaster) {
int ModBockId = TeamId % num_of_records;
if (TeamId < num_of_records)
lgcpyFct(global_buffer, ModBockId, reduce_data);
else
lgredFct(global_buffer, ModBockId, reduce_data);
__threadfence_system();
// Increment team counter.
// This counter is incremented by all teams in the current
// BUFFER_SIZE chunk.
ChunkTeamCount = atomicInc((uint32_t *)&Cnt, num_of_records - 1);
}
// Synchronize
if (checkSPMDMode(loc))
__kmpc_barrier(loc, global_tid);
// reduce_data is global or shared so before being reduced within the
// warp we need to bring it in local memory:
// local_reduce_data = reduce_data[i]
//
// Example for 3 reduction variables a, b, c (of potentially different
// types):
//
// buffer layout (struct of arrays):
// a, a, ..., a, b, b, ... b, c, c, ... c
// |__________|
// num_of_records
//
// local_data_reduce layout (struct):
// a, b, c
//
// Each thread will have a local struct containing the values to be
// reduced:
// 1. do reduction within each warp.
// 2. do reduction across warps.
// 3. write the final result to the main reduction variable
// by returning 1 in the thread holding the reduction result.
// Check if this is the very last team.
unsigned NumRecs = min(NumTeams, num_of_records);
if (ChunkTeamCount == NumTeams - Bound - 1) {
//
// Last team processing.
//
if (ThreadId >= NumRecs)
return 0;
NumThreads = roundToWarpsize(min(NumThreads, NumRecs));
if (ThreadId >= NumThreads)
return 0;
// Load from buffer and reduce.
glcpyFct(global_buffer, ThreadId, reduce_data);
for (uint32_t i = NumThreads + ThreadId; i < NumRecs; i += NumThreads)
glredFct(global_buffer, i, reduce_data);
// Reduce across warps to the warp master.
if (NumThreads > 1) {
gpu_regular_warp_reduce(reduce_data, shflFct);
// When we have more than [warpsize] number of threads
// a block reduction is performed here.
uint32_t ActiveThreads = min(NumRecs, NumThreads);
if (ActiveThreads > WARPSIZE) {
uint32_t WarpsNeeded = (ActiveThreads + WARPSIZE - 1) / WARPSIZE;
// Gather all the reduced values from each warp
// to the first warp.
cpyFct(reduce_data, WarpsNeeded);
uint32_t WarpId = ThreadId / WARPSIZE;
if (WarpId == 0)
gpu_irregular_warp_reduce(reduce_data, shflFct, WarpsNeeded,
ThreadId);
}
}
if (IsMaster) {
Cnt = 0;
IterCnt = 0;
return 1;
}
return 0;
}
if (IsMaster && ChunkTeamCount == num_of_records - 1) {
// Allow SIZE number of teams to proceed writing their
// intermediate results to the global buffer.
atomicAdd((uint32_t *)&IterCnt, num_of_records);
}
return 0;
}
@@ -1,9 +1,8 @@
//===--------- statequeue.h - NVPTX OpenMP GPU State Queue ------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -35,14 +34,14 @@ private:
static const uint32_t MAX_ID = (1u << 31) / SIZE / 2;
INLINE uint32_t ENQUEUE_TICKET();
INLINE uint32_t DEQUEUE_TICKET();
INLINE uint32_t ID(uint32_t ticket);
INLINE static uint32_t ID(uint32_t ticket);
INLINE bool IsServing(uint32_t slot, uint32_t id);
INLINE void PushElement(uint32_t slot, ElementType *element);
INLINE ElementType *PopElement(uint32_t slot);
INLINE void DoneServing(uint32_t slot, uint32_t id);
public:
INLINE omptarget_nvptx_Queue(){};
INLINE omptarget_nvptx_Queue() {}
INLINE void Enqueue(ElementType *element);
INLINE ElementType *Dequeue();
};
@@ -1,9 +1,8 @@
//===------- state-queue.cu - NVPTX OpenMP GPU State Queue ------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -30,7 +29,8 @@ INLINE uint32_t omptarget_nvptx_Queue<ElementType, SIZE>::DEQUEUE_TICKET() {
}
template <typename ElementType, uint32_t SIZE>
INLINE uint32_t omptarget_nvptx_Queue<ElementType, SIZE>::ID(uint32_t ticket) {
INLINE uint32_t
omptarget_nvptx_Queue<ElementType, SIZE>::ID(uint32_t ticket) {
return (ticket / SIZE) * 2;
}
+17 -13
View File
@@ -1,9 +1,8 @@
//===--------- support.h - NVPTX OpenMP support functions -------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -11,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
#include "target_impl.h"
////////////////////////////////////////////////////////////////////////////////
// Execution Parameters
////////////////////////////////////////////////////////////////////////////////
@@ -41,30 +41,34 @@ INLINE int GetThreadIdInBlock();
INLINE int GetBlockIdInKernel();
INLINE int GetNumberOfBlocksInKernel();
INLINE int GetNumberOfThreadsInBlock();
INLINE unsigned GetWarpId();
INLINE unsigned GetLaneId();
// get global ids to locate tread/team info (constant regardless of OMP)
INLINE int GetLogicalThreadIdInBlock();
INLINE int GetLogicalThreadIdInBlock(bool isSPMDExecutionMode);
INLINE int GetMasterThreadID();
INLINE int GetNumberOfWorkersInTeam();
// get OpenMP thread and team ids
INLINE int GetOmpThreadId(int threadId, bool isSPMDExecutionMode,
bool isRuntimeUninitialized); // omp_thread_num
INLINE int GetOmpThreadId(int threadId,
bool isSPMDExecutionMode); // omp_thread_num
INLINE int GetOmpTeamId(); // omp_team_num
// get OpenMP number of threads and team
INLINE int
GetNumberOfOmpThreads(int threadId, bool isSPMDExecutionMode,
bool isRuntimeUninitialized); // omp_num_threads
INLINE int GetNumberOfOmpTeams(); // omp_num_teams
INLINE int GetNumberOfOmpThreads(bool isSPMDExecutionMode); // omp_num_threads
INLINE int GetNumberOfOmpTeams(); // omp_num_teams
// get OpenMP number of procs
INLINE int GetNumberOfProcsInTeam();
INLINE int GetNumberOfProcsInDevice();
INLINE int GetNumberOfProcsInTeam(bool isSPMDExecutionMode);
INLINE int GetNumberOfProcsInDevice(bool isSPMDExecutionMode);
// masters
INLINE int IsTeamMaster(int ompThreadId);
// Parallel level
INLINE void IncParallelLevel(bool ActiveParallel, __kmpc_impl_lanemask_t Mask);
INLINE void DecParallelLevel(bool ActiveParallel, __kmpc_impl_lanemask_t Mask);
////////////////////////////////////////////////////////////////////////////////
// Memory
////////////////////////////////////////////////////////////////////////////////
+112 -31
View File
@@ -1,9 +1,8 @@
//===--------- supporti.h - NVPTX OpenMP support functions ------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -15,6 +14,8 @@
// Execution Parameters
////////////////////////////////////////////////////////////////////////////////
#include "target_impl.h"
INLINE void setExecutionParameters(ExecutionMode EMode, RuntimeMode RMode) {
execution_param = EMode;
execution_param |= RMode;
@@ -32,6 +33,59 @@ INLINE bool isRuntimeInitialized() {
return (execution_param & RuntimeMask) == RuntimeInitialized;
}
////////////////////////////////////////////////////////////////////////////////
// Execution Modes based on location parameter fields
////////////////////////////////////////////////////////////////////////////////
INLINE bool checkSPMDMode(kmp_Ident *loc) {
if (!loc)
return isSPMDMode();
// If SPMD is true then we are not in the UNDEFINED state so
// we can return immediately.
if (loc->reserved_2 & KMP_IDENT_SPMD_MODE)
return true;
// If not in SPMD mode and runtime required is a valid
// combination of flags so we can return immediately.
if (!(loc->reserved_2 & KMP_IDENT_SIMPLE_RT_MODE))
return false;
// We are in underfined state.
return isSPMDMode();
}
INLINE bool checkGenericMode(kmp_Ident *loc) {
return !checkSPMDMode(loc);
}
INLINE bool checkRuntimeUninitialized(kmp_Ident *loc) {
if (!loc)
return isRuntimeUninitialized();
// If runtime is required then we know we can't be
// in the undefined mode. We can return immediately.
if (!(loc->reserved_2 & KMP_IDENT_SIMPLE_RT_MODE))
return false;
// If runtime is required then we need to check is in
// SPMD mode or not. If not in SPMD mode then we end
// up in the UNDEFINED state that marks the orphaned
// functions.
if (loc->reserved_2 & KMP_IDENT_SPMD_MODE)
return true;
// Check if we are in an UNDEFINED state. Undefined is denoted by
// non-SPMD + noRuntimeRequired which is a combination that
// cannot actually happen. Undefined states is used to mark orphaned
// functions.
return isRuntimeUninitialized();
}
INLINE bool checkRuntimeInitialized(kmp_Ident *loc) {
return !checkRuntimeUninitialized(loc);
}
////////////////////////////////////////////////////////////////////////////////
// support: get info from machine
////////////////////////////////////////////////////////////////////////////////
@@ -50,6 +104,10 @@ INLINE int GetNumberOfBlocksInKernel() { return gridDim.x; }
INLINE int GetNumberOfThreadsInBlock() { return blockDim.x; }
INLINE unsigned GetWarpId() { return threadIdx.x / WARPSIZE; }
INLINE unsigned GetLaneId() { return threadIdx.x & (WARPSIZE - 1); }
////////////////////////////////////////////////////////////////////////////////
//
// Calls to the Generic Scheme Implementation Layer (assuming 1D layout)
@@ -77,13 +135,11 @@ INLINE int GetNumberOfWorkersInTeam() { return GetMasterThreadID(); }
// or a serial region by the master. If the master (whose CUDA thread
// id is GetMasterThreadID()) calls this routine, we return 0 because
// it is a shadow for the first worker.
INLINE int GetLogicalThreadIdInBlock() {
// return GetThreadIdInBlock() % GetMasterThreadID();
INLINE int GetLogicalThreadIdInBlock(bool isSPMDExecutionMode) {
// Implemented using control flow (predication) instead of with a modulo
// operation.
int tid = GetThreadIdInBlock();
if (isGenericMode() && tid >= GetMasterThreadID())
if (!isSPMDExecutionMode && tid >= GetMasterThreadID())
return 0;
else
return tid;
@@ -95,36 +151,32 @@ INLINE int GetLogicalThreadIdInBlock() {
//
////////////////////////////////////////////////////////////////////////////////
INLINE int GetOmpThreadId(int threadId, bool isSPMDExecutionMode,
bool isRuntimeUninitialized) {
INLINE int GetOmpThreadId(int threadId, bool isSPMDExecutionMode) {
// omp_thread_num
int rc;
if (isRuntimeUninitialized) {
if ((parallelLevel[GetWarpId()] & (OMP_ACTIVE_PARALLEL_LEVEL - 1)) > 1) {
rc = 0;
} else if (isSPMDExecutionMode) {
rc = GetThreadIdInBlock();
if (!isSPMDExecutionMode && rc >= GetMasterThreadID())
rc = 0;
} else {
omptarget_nvptx_TaskDescr *currTaskDescr =
omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(threadId);
ASSERT0(LT_FUSSY, currTaskDescr, "expected a top task descr");
rc = currTaskDescr->ThreadId();
}
return rc;
}
INLINE int GetNumberOfOmpThreads(int threadId, bool isSPMDExecutionMode,
bool isRuntimeUninitialized) {
INLINE int GetNumberOfOmpThreads(bool isSPMDExecutionMode) {
// omp_num_threads
int rc;
if (isRuntimeUninitialized) {
rc = isSPMDExecutionMode ? GetNumberOfThreadsInBlock()
: GetNumberOfThreadsInBlock() - WARPSIZE;
int Level = parallelLevel[GetWarpId()];
if (Level != OMP_ACTIVE_PARALLEL_LEVEL + 1) {
rc = 1;
} else if (isSPMDExecutionMode) {
rc = GetNumberOfThreadsInBlock();
} else {
omptarget_nvptx_TaskDescr *currTaskDescr =
omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(threadId);
ASSERT0(LT_FUSSY, currTaskDescr, "expected a top task descr");
rc = currTaskDescr->ThreadsInTeam();
rc = threadsInTeam;
}
return rc;
@@ -148,17 +200,46 @@ INLINE int GetNumberOfOmpTeams() {
INLINE int IsTeamMaster(int ompThreadId) { return (ompThreadId == 0); }
////////////////////////////////////////////////////////////////////////////////
// Parallel level
INLINE void IncParallelLevel(bool ActiveParallel, __kmpc_impl_lanemask_t Mask) {
__kmpc_impl_syncwarp(Mask);
__kmpc_impl_lanemask_t LaneMaskLt = __kmpc_impl_lanemask_lt();
unsigned Rank = __kmpc_impl_popc(Mask & LaneMaskLt);
if (Rank == 0) {
parallelLevel[GetWarpId()] +=
(1 + (ActiveParallel ? OMP_ACTIVE_PARALLEL_LEVEL : 0));
__threadfence();
}
__kmpc_impl_syncwarp(Mask);
}
INLINE void DecParallelLevel(bool ActiveParallel, __kmpc_impl_lanemask_t Mask) {
__kmpc_impl_syncwarp(Mask);
__kmpc_impl_lanemask_t LaneMaskLt = __kmpc_impl_lanemask_lt();
unsigned Rank = __kmpc_impl_popc(Mask & LaneMaskLt);
if (Rank == 0) {
parallelLevel[GetWarpId()] -=
(1 + (ActiveParallel ? OMP_ACTIVE_PARALLEL_LEVEL : 0));
__threadfence();
}
__kmpc_impl_syncwarp(Mask);
}
////////////////////////////////////////////////////////////////////////////////
// get OpenMP number of procs
// Get the number of processors in the device.
INLINE int GetNumberOfProcsInDevice() {
if (isGenericMode())
INLINE int GetNumberOfProcsInDevice(bool isSPMDExecutionMode) {
if (!isSPMDExecutionMode)
return GetNumberOfWorkersInTeam();
return GetNumberOfThreadsInBlock();
}
INLINE int GetNumberOfProcsInTeam() { return GetNumberOfProcsInDevice(); }
INLINE int GetNumberOfProcsInTeam(bool isSPMDExecutionMode) {
return GetNumberOfProcsInDevice(isSPMDExecutionMode);
}
////////////////////////////////////////////////////////////////////////////////
// Memory
@@ -169,20 +250,20 @@ INLINE unsigned long PadBytes(unsigned long size,
{
// compute the necessary padding to satisfy alignment constraint
ASSERT(LT_FUSSY, (alignment & (alignment - 1)) == 0,
"alignment %ld is not a power of 2\n", alignment);
"alignment %lu is not a power of 2\n", alignment);
return (~(unsigned long)size + 1) & (alignment - 1);
}
INLINE void *SafeMalloc(size_t size, const char *msg) // check if success
{
void *ptr = malloc(size);
PRINT(LD_MEM, "malloc data of size %zu for %s: 0x%llx\n", size, msg, P64(ptr));
ASSERT(LT_SAFETY, ptr, "failed to allocate %zu bytes for %s\n", size, msg);
PRINT(LD_MEM, "malloc data of size %llu for %s: 0x%llx\n",
(unsigned long long)size, msg, (unsigned long long)ptr);
return ptr;
}
INLINE void *SafeFree(void *ptr, const char *msg) {
PRINT(LD_MEM, "free data ptr 0x%llx for %s\n", P64(ptr), msg);
PRINT(LD_MEM, "free data ptr 0x%llx for %s\n", (unsigned long long)ptr, msg);
free(ptr);
return NULL;
}
+45 -43
View File
@@ -1,9 +1,8 @@
//===------------ sync.h - NVPTX OpenMP synchronizations --------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -12,16 +11,17 @@
//===----------------------------------------------------------------------===//
#include "omptarget-nvptx.h"
#include "target_impl.h"
////////////////////////////////////////////////////////////////////////////////
// KMP Ordered calls
////////////////////////////////////////////////////////////////////////////////
EXTERN void __kmpc_ordered(kmp_Indent *loc, int32_t tid) {
EXTERN void __kmpc_ordered(kmp_Ident *loc, int32_t tid) {
PRINT0(LD_IO, "call kmpc_ordered\n");
}
EXTERN void __kmpc_end_ordered(kmp_Indent *loc, int32_t tid) {
EXTERN void __kmpc_end_ordered(kmp_Ident *loc, int32_t tid) {
PRINT0(LD_IO, "call kmpc_end_ordered\n");
}
@@ -33,27 +33,24 @@ EXTERN void __kmpc_end_ordered(kmp_Indent *loc, int32_t tid) {
// FIXME: what if not all threads (warps) participate to the barrier?
// We may need to implement it differently
EXTERN int32_t __kmpc_cancel_barrier(kmp_Indent *loc_ref, int32_t tid) {
EXTERN int32_t __kmpc_cancel_barrier(kmp_Ident *loc_ref, int32_t tid) {
PRINT0(LD_IO, "call kmpc_cancel_barrier\n");
__kmpc_barrier(loc_ref, tid);
PRINT0(LD_SYNC, "completed kmpc_cancel_barrier\n");
return 0;
}
EXTERN void __kmpc_barrier(kmp_Indent *loc_ref, int32_t tid) {
if (isRuntimeUninitialized()) {
if (isSPMDMode())
__kmpc_barrier_simple_spmd(loc_ref, tid);
else
__kmpc_barrier_simple_generic(loc_ref, tid);
EXTERN void __kmpc_barrier(kmp_Ident *loc_ref, int32_t tid) {
if (checkRuntimeUninitialized(loc_ref)) {
ASSERT0(LT_FUSSY, checkSPMDMode(loc_ref),
"Expected SPMD mode with uninitialized runtime.");
__kmpc_barrier_simple_spmd(loc_ref, tid);
} else {
tid = GetLogicalThreadIdInBlock();
omptarget_nvptx_TaskDescr *currTaskDescr =
omptarget_nvptx_threadPrivateContext->GetTopLevelTaskDescr(tid);
int numberOfActiveOMPThreads = GetNumberOfOmpThreads(
tid, isSPMDMode(), /*isRuntimeUninitialized=*/false);
tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc_ref));
int numberOfActiveOMPThreads =
GetNumberOfOmpThreads(checkSPMDMode(loc_ref));
if (numberOfActiveOMPThreads > 1) {
if (isSPMDMode()) {
if (checkSPMDMode(loc_ref)) {
__kmpc_barrier_simple_spmd(loc_ref, tid);
} else {
// The #threads parameter must be rounded up to the WARPSIZE.
@@ -62,10 +59,13 @@ EXTERN void __kmpc_barrier(kmp_Indent *loc_ref, int32_t tid) {
PRINT(LD_SYNC,
"call kmpc_barrier with %d omp threads, sync parameter %d\n",
numberOfActiveOMPThreads, threads);
(int)numberOfActiveOMPThreads, (int)threads);
// Barrier #1 is for synchronization among active threads.
named_sync(L1_BARRIER, threads);
}
} else {
// Still need to flush the memory per the standard.
__kmpc_flush(loc_ref);
} // numberOfActiveOMPThreads > 1
PRINT0(LD_SYNC, "completed kmpc_barrier\n");
}
@@ -73,15 +73,15 @@ EXTERN void __kmpc_barrier(kmp_Indent *loc_ref, int32_t tid) {
// Emit a simple barrier call in SPMD mode. Assumes the caller is in an L0
// parallel region and that all worker threads participate.
EXTERN void __kmpc_barrier_simple_spmd(kmp_Indent *loc_ref, int32_t tid) {
EXTERN void __kmpc_barrier_simple_spmd(kmp_Ident *loc_ref, int32_t tid) {
PRINT0(LD_SYNC, "call kmpc_barrier_simple_spmd\n");
__syncthreads();
__kmpc_impl_syncthreads();
PRINT0(LD_SYNC, "completed kmpc_barrier_simple_spmd\n");
}
// Emit a simple barrier call in Generic mode. Assumes the caller is in an L0
// parallel region and that all worker threads participate.
EXTERN void __kmpc_barrier_simple_generic(kmp_Indent *loc_ref, int32_t tid) {
EXTERN void __kmpc_barrier_simple_generic(kmp_Ident *loc_ref, int32_t tid) {
int numberOfActiveOMPThreads = GetNumberOfThreadsInBlock() - WARPSIZE;
// The #threads parameter must be rounded up to the WARPSIZE.
int threads =
@@ -90,7 +90,7 @@ EXTERN void __kmpc_barrier_simple_generic(kmp_Indent *loc_ref, int32_t tid) {
PRINT(LD_SYNC,
"call kmpc_barrier_simple_generic with %d omp threads, sync parameter "
"%d\n",
numberOfActiveOMPThreads, threads);
(int)numberOfActiveOMPThreads, (int)threads);
// Barrier #1 is for synchronization among active threads.
named_sync(L1_BARRIER, threads);
PRINT0(LD_SYNC, "completed kmpc_barrier_simple_generic\n");
@@ -100,37 +100,30 @@ EXTERN void __kmpc_barrier_simple_generic(kmp_Indent *loc_ref, int32_t tid) {
// KMP MASTER
////////////////////////////////////////////////////////////////////////////////
INLINE int32_t IsMaster() {
// only the team master updates the state
int tid = GetLogicalThreadIdInBlock();
int ompThreadId = GetOmpThreadId(tid, isSPMDMode(), isRuntimeUninitialized());
return IsTeamMaster(ompThreadId);
}
EXTERN int32_t __kmpc_master(kmp_Indent *loc, int32_t global_tid) {
EXTERN int32_t __kmpc_master(kmp_Ident *loc, int32_t global_tid) {
PRINT0(LD_IO, "call kmpc_master\n");
return IsMaster();
return IsTeamMaster(global_tid);
}
EXTERN void __kmpc_end_master(kmp_Indent *loc, int32_t global_tid) {
EXTERN void __kmpc_end_master(kmp_Ident *loc, int32_t global_tid) {
PRINT0(LD_IO, "call kmpc_end_master\n");
ASSERT0(LT_FUSSY, IsMaster(), "expected only master here");
ASSERT0(LT_FUSSY, IsTeamMaster(global_tid), "expected only master here");
}
////////////////////////////////////////////////////////////////////////////////
// KMP SINGLE
////////////////////////////////////////////////////////////////////////////////
EXTERN int32_t __kmpc_single(kmp_Indent *loc, int32_t global_tid) {
EXTERN int32_t __kmpc_single(kmp_Ident *loc, int32_t global_tid) {
PRINT0(LD_IO, "call kmpc_single\n");
// decide to implement single with master; master get the single
return IsMaster();
return IsTeamMaster(global_tid);
}
EXTERN void __kmpc_end_single(kmp_Indent *loc, int32_t global_tid) {
EXTERN void __kmpc_end_single(kmp_Ident *loc, int32_t global_tid) {
PRINT0(LD_IO, "call kmpc_end_single\n");
// decide to implement single with master: master get the single
ASSERT0(LT_FUSSY, IsMaster(), "expected only master here");
ASSERT0(LT_FUSSY, IsTeamMaster(global_tid), "expected only master here");
// sync barrier is explicitely called... so that is not a problem
}
@@ -138,16 +131,25 @@ EXTERN void __kmpc_end_single(kmp_Indent *loc, int32_t global_tid) {
// Flush
////////////////////////////////////////////////////////////////////////////////
EXTERN void __kmpc_flush(kmp_Indent *loc) {
EXTERN void __kmpc_flush(kmp_Ident *loc) {
PRINT0(LD_IO, "call kmpc_flush\n");
__threadfence_block();
__threadfence();
}
////////////////////////////////////////////////////////////////////////////////
// Vote
////////////////////////////////////////////////////////////////////////////////
EXTERN int32_t __kmpc_warp_active_thread_mask() {
EXTERN __kmpc_impl_lanemask_t __kmpc_warp_active_thread_mask() {
PRINT0(LD_IO, "call __kmpc_warp_active_thread_mask\n");
return __ACTIVEMASK();
return __kmpc_impl_activemask();
}
////////////////////////////////////////////////////////////////////////////////
// Syncwarp
////////////////////////////////////////////////////////////////////////////////
EXTERN void __kmpc_syncwarp(__kmpc_impl_lanemask_t Mask) {
PRINT0(LD_IO, "call __kmpc_syncwarp\n");
__kmpc_impl_syncwarp(Mask);
}
@@ -0,0 +1,100 @@
//===------------ target_impl.h - NVPTX OpenMP GPU options ------- CUDA -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Definitions of target specific functions
//
//===----------------------------------------------------------------------===//
#ifndef _TARGET_IMPL_H_
#define _TARGET_IMPL_H_
#include <stdint.h>
#include "option.h"
INLINE void __kmpc_impl_unpack(uint64_t val, uint32_t &lo, uint32_t &hi) {
asm volatile("mov.b64 {%0,%1}, %2;" : "=r"(lo), "=r"(hi) : "l"(val));
}
INLINE uint64_t __kmpc_impl_pack(uint32_t lo, uint32_t hi) {
uint64_t val;
asm volatile("mov.b64 %0, {%1,%2};" : "=l"(val) : "r"(lo), "r"(hi));
return val;
}
static const __kmpc_impl_lanemask_t __kmpc_impl_all_lanes =
UINT32_C(0xffffffff);
INLINE __kmpc_impl_lanemask_t __kmpc_impl_lanemask_lt() {
__kmpc_impl_lanemask_t res;
asm("mov.u32 %0, %%lanemask_lt;" : "=r"(res));
return res;
}
INLINE __kmpc_impl_lanemask_t __kmpc_impl_lanemask_gt() {
__kmpc_impl_lanemask_t res;
asm("mov.u32 %0, %%lanemask_gt;" : "=r"(res));
return res;
}
INLINE uint32_t __kmpc_impl_ffs(uint32_t x) { return __ffs(x); }
INLINE uint32_t __kmpc_impl_popc(uint32_t x) { return __popc(x); }
#ifndef CUDA_VERSION
#error CUDA_VERSION macro is undefined, something wrong with cuda.
#endif
// In Cuda 9.0, __ballot(1) from Cuda 8.0 is replaced with __activemask().
INLINE __kmpc_impl_lanemask_t __kmpc_impl_activemask() {
#if CUDA_VERSION >= 9000
return __activemask();
#else
return __ballot(1);
#endif
}
// In Cuda 9.0, the *_sync() version takes an extra argument 'mask'.
INLINE int32_t __kmpc_impl_shfl_sync(__kmpc_impl_lanemask_t Mask, int32_t Var,
int32_t SrcLane) {
#if CUDA_VERSION >= 9000
return __shfl_sync(Mask, Var, SrcLane);
#else
return __shfl(Var, SrcLane);
#endif // CUDA_VERSION
}
INLINE int32_t __kmpc_impl_shfl_down_sync(__kmpc_impl_lanemask_t Mask,
int32_t Var, uint32_t Delta,
int32_t Width) {
#if CUDA_VERSION >= 9000
return __shfl_down_sync(Mask, Var, Delta, Width);
#else
return __shfl_down(Var, Delta, Width);
#endif // CUDA_VERSION
}
INLINE void __kmpc_impl_syncthreads() {
// Use original __syncthreads if compiled by nvcc or clang >= 9.0.
#if !defined(__clang__) || __clang_major__ >= 9
__syncthreads();
#else
asm volatile("bar.sync %0;" : : "r"(0) : "memory");
#endif // __clang__
}
INLINE void __kmpc_impl_syncwarp(__kmpc_impl_lanemask_t Mask) {
#if CUDA_VERSION >= 9000
__syncwarp(Mask);
#else
// In Cuda < 9.0 no need to sync threads in warps.
#endif // CUDA_VERSION
}
#endif
+33 -25
View File
@@ -1,9 +1,8 @@
//===------------- task.h - NVPTX OpenMP tasks support ----------- CUDA -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -31,7 +30,7 @@
#include "omptarget-nvptx.h"
EXTERN kmp_TaskDescr *__kmpc_omp_task_alloc(
kmp_Indent *loc, // unused
kmp_Ident *loc, // unused
uint32_t global_tid, // unused
int32_t flag, // unused (because in our impl, all are immediately exec
size_t sizeOfTaskInclPrivate, size_t sizeOfSharedTable,
@@ -39,14 +38,15 @@ EXTERN kmp_TaskDescr *__kmpc_omp_task_alloc(
PRINT(LD_IO,
"call __kmpc_omp_task_alloc(size priv&struct %lld, shared %lld, "
"fct 0x%llx)\n",
P64(sizeOfTaskInclPrivate), P64(sizeOfSharedTable), P64(taskSub));
(long long)sizeOfTaskInclPrivate, (long long)sizeOfSharedTable,
(unsigned long long)taskSub);
// want task+priv to be a multiple of 8 bytes
size_t padForTaskInclPriv = PadBytes(sizeOfTaskInclPrivate, sizeof(void *));
sizeOfTaskInclPrivate += padForTaskInclPriv;
size_t kmpSize = sizeOfTaskInclPrivate + sizeOfSharedTable;
ASSERT(LT_FUSSY, sizeof(omptarget_nvptx_TaskDescr) % sizeof(void *) == 0,
"need task descr of size %d to be a multiple of %d\n",
sizeof(omptarget_nvptx_TaskDescr), sizeof(void *));
(int)sizeof(omptarget_nvptx_TaskDescr), (int)sizeof(void *));
size_t totSize = sizeof(omptarget_nvptx_TaskDescr) + kmpSize;
omptarget_nvptx_ExplicitTaskDescr *newExplicitTaskDescr =
(omptarget_nvptx_ExplicitTaskDescr *)SafeMalloc(
@@ -63,24 +63,27 @@ EXTERN kmp_TaskDescr *__kmpc_omp_task_alloc(
newKmpTaskDescr->sub = taskSub;
newKmpTaskDescr->destructors = NULL;
PRINT(LD_TASK, "return with task descr kmp: 0x%llx, omptarget-nvptx 0x%llx\n",
P64(newKmpTaskDescr), P64(newExplicitTaskDescr));
(unsigned long long)newKmpTaskDescr,
(unsigned long long)newExplicitTaskDescr);
return newKmpTaskDescr;
}
EXTERN int32_t __kmpc_omp_task(kmp_Indent *loc, uint32_t global_tid,
EXTERN int32_t __kmpc_omp_task(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newKmpTaskDescr) {
return __kmpc_omp_task_with_deps(loc, global_tid, newKmpTaskDescr, 0, 0, 0,
0);
}
EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Indent *loc, uint32_t global_tid,
EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newKmpTaskDescr,
int32_t depNum, void *depList,
int32_t noAliasDepNum,
void *noAliasDepList) {
PRINT(LD_IO, "call to __kmpc_omp_task_with_deps(task 0x%llx)\n",
P64(newKmpTaskDescr));
ASSERT0(LT_FUSSY, checkRuntimeInitialized(loc),
"Runtime must be initialized.");
// 1. get explict task descr from kmp task descr
omptarget_nvptx_ExplicitTaskDescr *newExplicitTaskDescr =
(omptarget_nvptx_ExplicitTaskDescr *)SUB_BYTES(
@@ -92,7 +95,7 @@ EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Indent *loc, uint32_t global_tid,
"bad assumptions");
// 2. push new context: update new task descriptor
int tid = GetLogicalThreadIdInBlock();
int tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_TaskDescr *parentTaskDescr = getMyTopTaskDescriptor(tid);
newTaskDescr->CopyForExplicitTask(parentTaskDescr);
// set new task descriptor as top
@@ -100,10 +103,11 @@ EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Indent *loc, uint32_t global_tid,
// 3. call sub
PRINT(LD_TASK, "call task sub 0x%llx(task descr 0x%llx)\n",
P64(newKmpTaskDescr->sub), P64(newKmpTaskDescr));
(unsigned long long)newKmpTaskDescr->sub,
(unsigned long long)newKmpTaskDescr);
newKmpTaskDescr->sub(0, newKmpTaskDescr);
PRINT(LD_TASK, "return from call task sub 0x%llx()\n",
P64(newKmpTaskDescr->sub));
(unsigned long long)newKmpTaskDescr->sub);
// 4. pop context
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(tid,
@@ -113,10 +117,12 @@ EXTERN int32_t __kmpc_omp_task_with_deps(kmp_Indent *loc, uint32_t global_tid,
return 0;
}
EXTERN void __kmpc_omp_task_begin_if0(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_omp_task_begin_if0(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newKmpTaskDescr) {
PRINT(LD_IO, "call to __kmpc_omp_task_begin_if0(task 0x%llx)\n",
P64(newKmpTaskDescr));
(unsigned long long)newKmpTaskDescr);
ASSERT0(LT_FUSSY, checkRuntimeInitialized(loc),
"Runtime must be initialized.");
// 1. get explict task descr from kmp task descr
omptarget_nvptx_ExplicitTaskDescr *newExplicitTaskDescr =
(omptarget_nvptx_ExplicitTaskDescr *)SUB_BYTES(
@@ -128,7 +134,7 @@ EXTERN void __kmpc_omp_task_begin_if0(kmp_Indent *loc, uint32_t global_tid,
"bad assumptions");
// 2. push new context: update new task descriptor
int tid = GetLogicalThreadIdInBlock();
int tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_TaskDescr *parentTaskDescr = getMyTopTaskDescriptor(tid);
newTaskDescr->CopyForExplicitTask(parentTaskDescr);
// set new task descriptor as top
@@ -137,10 +143,12 @@ EXTERN void __kmpc_omp_task_begin_if0(kmp_Indent *loc, uint32_t global_tid,
// 4 & 5 ... done in complete
}
EXTERN void __kmpc_omp_task_complete_if0(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_omp_task_complete_if0(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newKmpTaskDescr) {
PRINT(LD_IO, "call to __kmpc_omp_task_complete_if0(task 0x%llx)\n",
P64(newKmpTaskDescr));
(unsigned long long)newKmpTaskDescr);
ASSERT0(LT_FUSSY, checkRuntimeInitialized(loc),
"Runtime must be initialized.");
// 1. get explict task descr from kmp task descr
omptarget_nvptx_ExplicitTaskDescr *newExplicitTaskDescr =
(omptarget_nvptx_ExplicitTaskDescr *)SUB_BYTES(
@@ -154,44 +162,44 @@ EXTERN void __kmpc_omp_task_complete_if0(kmp_Indent *loc, uint32_t global_tid,
omptarget_nvptx_TaskDescr *parentTaskDescr = newTaskDescr->GetPrevTaskDescr();
// 3... noting to call... is inline
// 4. pop context
int tid = GetLogicalThreadIdInBlock();
int tid = GetLogicalThreadIdInBlock(checkSPMDMode(loc));
omptarget_nvptx_threadPrivateContext->SetTopLevelTaskDescr(tid,
parentTaskDescr);
// 5. free
SafeFree(newExplicitTaskDescr, "explicit task descriptor");
}
EXTERN void __kmpc_omp_wait_deps(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_omp_wait_deps(kmp_Ident *loc, uint32_t global_tid,
int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList) {
PRINT0(LD_IO, "call to __kmpc_omp_wait_deps(..)\n");
// nothing to do as all our tasks are executed as final
}
EXTERN void __kmpc_taskgroup(kmp_Indent *loc, uint32_t global_tid) {
EXTERN void __kmpc_taskgroup(kmp_Ident *loc, uint32_t global_tid) {
PRINT0(LD_IO, "call to __kmpc_taskgroup(..)\n");
// nothing to do as all our tasks are executed as final
}
EXTERN void __kmpc_end_taskgroup(kmp_Indent *loc, uint32_t global_tid) {
EXTERN void __kmpc_end_taskgroup(kmp_Ident *loc, uint32_t global_tid) {
PRINT0(LD_IO, "call to __kmpc_end_taskgroup(..)\n");
// nothing to do as all our tasks are executed as final
}
EXTERN int32_t __kmpc_omp_taskyield(kmp_Indent *loc, uint32_t global_tid,
EXTERN int32_t __kmpc_omp_taskyield(kmp_Ident *loc, uint32_t global_tid,
int end_part) {
PRINT0(LD_IO, "call to __kmpc_taskyield()\n");
// do nothing: tasks are executed immediately, no yielding allowed
return 0;
}
EXTERN int32_t __kmpc_omp_taskwait(kmp_Indent *loc, uint32_t global_tid) {
EXTERN int32_t __kmpc_omp_taskwait(kmp_Ident *loc, uint32_t global_tid) {
PRINT0(LD_IO, "call to __kmpc_taskwait()\n");
// nothing to do as all our tasks are executed as final
return 0;
}
EXTERN void __kmpc_taskloop(kmp_Indent *loc, uint32_t global_tid,
EXTERN void __kmpc_taskloop(kmp_Ident *loc, uint32_t global_tid,
kmp_TaskDescr *newKmpTaskDescr, int if_val,
uint64_t *lb, uint64_t *ub, int64_t st, int nogroup,
int32_t sched, uint64_t grainsize, void *task_dup) {
@@ -0,0 +1,26 @@
if(NOT OPENMP_TEST_COMPILER_ID STREQUAL "Clang")
# Silently return, no need to annoy the user.
return()
endif()
set(deps omptarget-nvptx omptarget omp)
if(LIBOMPTARGET_NVPTX_ENABLE_BCLIB)
set(deps ${deps} omptarget-nvptx-bc)
endif()
# Don't run by default.
set(EXCLUDE_FROM_ALL True)
# Run with only one thread to only launch one application to the GPU at a time.
add_openmp_testsuite(check-libomptarget-nvptx
"Running libomptarget-nvptx tests" ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${deps} ARGS -j1)
set(LIBOMPTARGET_NVPTX_TEST_FLAGS "" CACHE STRING
"Extra compiler flags to send to the test compiler.")
set(LIBOMPTARGET_NVPTX_TEST_OPENMP_FLAGS
"-fopenmp -fopenmp-targets=nvptx64-nvidia-cuda" CACHE STRING
"OpenMP compiler flags to use for testing libomptarget-nvptx.")
# Configure the lit.site.cfg.in file
set(AUTO_GEN_COMMENT "## Autogenerated by libomptarget-nvptx configuration.\n# Do not edit!")
configure_file(lit.site.cfg.in lit.site.cfg @ONLY)
@@ -0,0 +1,38 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
const int MaxThreads = 1024;
int main(int argc, char *argv[]) {
int cancellation = -1, dynamic = -1, nested = -1, maxActiveLevels = -1;
#pragma omp target map(cancellation, dynamic, nested, maxActiveLevels)
{
// libomptarget-nvptx doesn't support cancellation.
cancellation = omp_get_cancellation();
// No support for dynamic adjustment of the number of threads.
omp_set_dynamic(1);
dynamic = omp_get_dynamic();
// libomptarget-nvptx doesn't support nested parallelism.
omp_set_nested(1);
nested = omp_get_nested();
omp_set_max_active_levels(42);
maxActiveLevels = omp_get_max_active_levels();
}
// CHECK: cancellation = 0
printf("cancellation = %d\n", cancellation);
// CHECK: dynamic = 0
printf("dynamic = %d\n", dynamic);
// CHECK: nested = 0
printf("nested = %d\n", nested);
// CHECK: maxActiveLevels = 1
printf("maxActiveLevels = %d\n", maxActiveLevels);
return 0;
}
@@ -0,0 +1,46 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int MaxThreadsL1 = -1, MaxThreadsL2 = -1;
#pragma omp declare reduction(unique:int \
: omp_out = (omp_in == 1 ? omp_in : omp_out)) \
initializer(omp_priv = -1)
// Non-SPMD mode.
#pragma omp target teams map(MaxThreadsL1, MaxThreadsL2) thread_limit(32) \
num_teams(1)
{
MaxThreadsL1 = omp_get_max_threads();
#pragma omp parallel reduction(unique : MaxThreadsL2)
{ MaxThreadsL2 = omp_get_max_threads(); }
}
// CHECK: Non-SPMD MaxThreadsL1 = 32
printf("Non-SPMD MaxThreadsL1 = %d\n", MaxThreadsL1);
// CHECK: Non-SPMD MaxThreadsL2 = 1
printf("Non-SPMD MaxThreadsL2 = %d\n", MaxThreadsL2);
// SPMD mode with full runtime
MaxThreadsL2 = -1;
#pragma omp target parallel reduction(unique : MaxThreadsL2)
{ MaxThreadsL2 = omp_get_max_threads(); }
// CHECK: SPMD with full runtime MaxThreadsL2 = 1
printf("SPMD with full runtime MaxThreadsL2 = %d\n", MaxThreadsL2);
// SPMD mode without runtime
MaxThreadsL2 = -1;
#pragma omp target parallel for reduction(unique : MaxThreadsL2)
for (int I = 0; I < 2; ++I) {
MaxThreadsL2 = omp_get_max_threads();
}
// CHECK: SPMD without runtime MaxThreadsL2 = 1
printf("SPMD without runtime MaxThreadsL2 = %d\n", MaxThreadsL2);
return 0;
}
@@ -0,0 +1,72 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int ThreadLimitL0 = -1, ThreadLimitL1 = -1, ThreadLimitL2 = -1;
#pragma omp declare reduction(unique64:int \
: omp_out = (omp_in == 64 ? omp_in : omp_out)) \
initializer(omp_priv = -1)
#pragma omp declare reduction(unique32:int \
: omp_out = (omp_in == 32 ? omp_in : omp_out)) \
initializer(omp_priv = -1)
// Non-SPMD mode.
#pragma omp target teams map(ThreadLimitL0, ThreadLimitL1, ThreadLimitL2) \
thread_limit(64) num_teams(1)
{
ThreadLimitL0 = omp_get_thread_limit();
#pragma omp parallel reduction(unique64 \
: ThreadLimitL1, ThreadLimitL2) num_threads(32)
{
ThreadLimitL1 = omp_get_thread_limit();
#pragma omp parallel reduction(unique64 : ThreadLimitL2)
{ ThreadLimitL2 = omp_get_thread_limit(); }
}
}
// CHECK: Non-SPMD ThreadLimitL0 = 64
printf("Non-SPMD ThreadLimitL0 = %d\n", ThreadLimitL0);
// CHECK: Non-SPMD ThreadLimitL1 = 64
printf("Non-SPMD ThreadLimitL1 = %d\n", ThreadLimitL1);
// CHECK: Non-SPMD ThreadLimitL2 = 64
printf("Non-SPMD ThreadLimitL2 = %d\n", ThreadLimitL2);
// SPMD mode with full runtime
ThreadLimitL1 = -1;
ThreadLimitL2 = -1;
#pragma omp target parallel reduction(unique32 \
: ThreadLimitL1, ThreadLimitL2) \
num_threads(32)
{
ThreadLimitL1 = omp_get_thread_limit();
#pragma omp parallel reduction(unique32 : ThreadLimitL2)
{ ThreadLimitL2 = omp_get_thread_limit(); }
}
// CHECK: SPMD with full runtime ThreadLimitL1 = 32
printf("SPMD with full runtime ThreadLimitL1 = %d\n", ThreadLimitL1);
// CHECK: SPMD with full runtime ThreadLimitL2 = 32
printf("SPMD with full runtime ThreadLimitL2 = %d\n", ThreadLimitL2);
// SPMD mode without runtime
ThreadLimitL1 = -1;
ThreadLimitL2 = -1;
#pragma omp target parallel for reduction(unique32 \
: ThreadLimitL1, ThreadLimitL2) \
num_threads(32)
for (int I = 0; I < 2; ++I) {
ThreadLimitL1 = omp_get_thread_limit();
#pragma omp parallel reduction(unique32 : ThreadLimitL2)
{ ThreadLimitL2 = omp_get_thread_limit(); }
}
// CHECK: SPMD without runtime ThreadLimitL1 = 32
printf("SPMD without runtime ThreadLimitL1 = %d\n", ThreadLimitL1);
// CHECK: SPMD without runtime ThreadLimitL2 = 32
printf("SPMD without runtime ThreadLimitL2 = %d\n", ThreadLimitL2);
return 0;
}
@@ -0,0 +1,55 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
#pragma omp declare target
static void putValueInParallel(int *ptr, int value) {
#pragma omp parallel
{
*ptr = value;
}
}
static int getId() {
int id;
putValueInParallel(&id, omp_get_thread_num());
return id;
}
#pragma omp end declare target
const int MaxThreads = 1024;
const int Threads = 64;
int main(int argc, char *argv[]) {
int master;
int check[MaxThreads];
for (int i = 0; i < MaxThreads; i++) {
check[i] = 0;
}
#pragma omp target map(master, check[:])
{
master = getId();
#pragma omp parallel num_threads(Threads)
{
check[omp_get_thread_num()] = getId();
}
}
// CHECK: master = 0.
printf("master = %d.\n", master);
// CHECK-NOT: invalid
for (int i = 0; i < MaxThreads; i++) {
if (i < Threads) {
if (check[i] != i) {
printf("invalid: check[%d] should be %d, is %d\n", i, i, check[i]);
}
} else if (check[i] != 0) {
printf("invalid: check[%d] should be 0, is %d\n", i, check[i]);
}
}
return 0;
}
@@ -0,0 +1,69 @@
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
# Configuration file for the 'lit' test runner.
import os
import lit.formats
# Tell pylint that we know config and lit_config exist somewhere.
if 'PYLINT_IMPORT' in os.environ:
config = object()
lit_config = object()
def prepend_library_path(name, value, sep):
if name in config.environment:
config.environment[name] = value + sep + config.environment[name]
else:
config.environment[name] = value
# name: The name of this test suite.
config.name = 'libomptarget-nvptx'
# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.c', '.cpp', '.cc']
# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)
# test_exec_root: The root object directory where output is placed
config.test_exec_root = config.binary_dir
# test format
config.test_format = lit.formats.ShTest()
# compiler flags
config.test_flags = " -I " + config.omp_header_directory + \
" -L " + config.library_dir + \
" --libomptarget-nvptx-path=" + config.library_dir;
if config.omp_host_rtl_directory:
config.test_flags = config.test_flags + \
" -L " + config.omp_host_rtl_directory
config.test_flags = config.test_flags + " " + config.test_extra_flags
# Setup environment to find dynamic library at runtime.
prepend_library_path('LD_LIBRARY_PATH', config.library_dir, ":")
prepend_library_path('LD_LIBRARY_PATH', config.omp_host_rtl_directory, ":")
# Forbid fallback to host.
config.environment["OMP_TARGET_OFFLOAD"] = "MANDATORY"
# substitutions
config.substitutions.append(("%compilexx-run-and-check",
"%compilexx-and-run | " + config.libomptarget_filecheck + " %s"))
config.substitutions.append(("%compile-run-and-check",
"%compile-and-run | " + config.libomptarget_filecheck + " %s"))
config.substitutions.append(("%compilexx-and-run", "%compilexx && %run"))
config.substitutions.append(("%compile-and-run", "%compile && %run"))
config.substitutions.append(("%compilexx",
"%clangxx %openmp_flags %flags %s -o %t"))
config.substitutions.append(("%compile",
"%clang %openmp_flags %flags %s -o %t"))
config.substitutions.append(("%clangxx", config.test_cxx_compiler))
config.substitutions.append(("%clang", config.test_c_compiler))
config.substitutions.append(("%openmp_flags", config.test_openmp_flags))
config.substitutions.append(("%flags", config.test_flags))
config.substitutions.append(("%run", "%t"))
@@ -0,0 +1,14 @@
@AUTO_GEN_COMMENT@
config.test_c_compiler = "@OPENMP_TEST_C_COMPILER@"
config.test_cxx_compiler = "@OPENMP_TEST_CXX_COMPILER@"
config.test_openmp_flags = "@LIBOMPTARGET_NVPTX_TEST_OPENMP_FLAGS@"
config.test_extra_flags = "@LIBOMPTARGET_NVPTX_TEST_FLAGS@"
config.binary_dir = "@CMAKE_CURRENT_BINARY_DIR@"
config.library_dir = "@LIBOMPTARGET_LIBRARY_DIR@"
config.omp_header_directory = "@LIBOMPTARGET_OPENMP_HEADER_FOLDER@"
config.omp_host_rtl_directory = "@LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER@"
config.libomptarget_filecheck = "@OPENMP_FILECHECK_EXECUTABLE@"
# Let the main config do the real work.
lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
@@ -0,0 +1,37 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int data, out, flag = 0;
#pragma omp target teams num_teams(2) map(tofrom \
: out) map(to \
: data, flag) \
thread_limit(1)
#pragma omp parallel num_threads(1)
{
if (omp_get_team_num() == 0) {
/* Write to the data buffer that will be read by thread in team 1 */
data = 42;
/* Flush data to thread in team 1 */
#pragma omp barrier
/* Set flag to release thread in team 1 */
#pragma omp atomic write
flag = 1;
} else if (omp_get_team_num() == 1) {
/* Loop until we see the update to the flag */
int val;
do {
#pragma omp atomic read
val = flag;
} while (val < 1);
out = data;
#pragma omp barrier
}
}
// CHECK: out=42.
/* Value of out will be 42 */
printf("out=%d.\n", out);
return !(out == 42);
}
@@ -0,0 +1,35 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int data, out, flag = 0;
#pragma omp target parallel num_threads(64) map(tofrom \
: out, flag) map(to \
: data)
{
if (omp_get_thread_num() == 0) {
/* Write to the data buffer that will be read by thread */
data = 42;
/* Flush data to thread 32 */
#pragma omp flush(data)
/* Set flag to release thread 32 */
#pragma omp atomic write
flag = 1;
} else if (omp_get_thread_num() == 32) {
/* Loop until we see the update to the flag */
int val;
do {
#pragma omp atomic read
val = flag;
} while (val < 1);
out = data;
#pragma omp flush(out)
}
}
// CHECK: out=42.
/* Value of out will be 42 */
printf("out=%d.\n", out);
return !(out == 42);
}
@@ -0,0 +1,151 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
const int MaxThreads = 1024;
const int NumThreads = 64;
int main(int argc, char *argv[]) {
int level = -1, activeLevel = -1;
// The expected value is -1, initialize to different value.
int ancestorTNumNeg = 1, teamSizeNeg = 1;
int ancestorTNum0 = -1, teamSize0 = -1;
// The expected value is -1, initialize to different value.
int ancestorTNum1 = 1, teamSize1 = 1;
int check1[MaxThreads];
int check2[MaxThreads];
int check3[MaxThreads];
int check4[MaxThreads];
for (int i = 0; i < MaxThreads; i++) {
check1[i] = check2[i] = check3[i] = check4[i] = 0;
}
#pragma omp target map(level, activeLevel, ancestorTNumNeg, teamSizeNeg) \
map(ancestorTNum0, teamSize0, ancestorTNum1, teamSize1) \
map(check1[:], check2[:], check3[:], check4[:])
{
level = omp_get_level();
activeLevel = omp_get_active_level();
// Expected to return -1.
ancestorTNumNeg = omp_get_ancestor_thread_num(-1);
teamSizeNeg = omp_get_team_size(-1);
// Expected to return 0 and 1.
ancestorTNum0 = omp_get_ancestor_thread_num(0);
teamSize0 = omp_get_team_size(0);
// Expected to return -1 because the requested level is larger than
// the nest level.
ancestorTNum1 = omp_get_ancestor_thread_num(1);
teamSize1 = omp_get_team_size(1);
// Expecting active parallel region.
#pragma omp parallel num_threads(NumThreads)
{
int id = omp_get_thread_num();
// Multiply return value of omp_get_level by 5 to avoid that this test
// passes if both API calls return wrong values.
check1[id] += omp_get_level() * 5 + omp_get_active_level();
// Expected to return 0 and 1.
check2[id] += omp_get_ancestor_thread_num(0) + 5 * omp_get_team_size(0);
// Expected to return the current thread num.
check2[id] += (omp_get_ancestor_thread_num(1) - id);
// Exepcted to return the current number of threads.
check2[id] += 3 * omp_get_team_size(1);
// Expected to return -1, see above.
check2[id] += omp_get_ancestor_thread_num(2) + omp_get_team_size(2);
// Expecting serialized parallel region.
#pragma omp parallel
{
#pragma omp atomic
check3[id] += omp_get_level() * 5 + omp_get_active_level();
// Expected to return 0 and 1.
int check4Inc = omp_get_ancestor_thread_num(0) + 5 * omp_get_team_size(0);
// Expected to return the parent thread num.
check4Inc += (omp_get_ancestor_thread_num(1) - id);
// Exepcted to return the number of threads in the active parallel region.
check4Inc += 3 * omp_get_team_size(1);
// Exptected to return 0 and 1.
check4Inc += omp_get_ancestor_thread_num(2) + 3 * omp_get_team_size(2);
// Expected to return -1, see above.
check4Inc += omp_get_ancestor_thread_num(3) + omp_get_team_size(3);
#pragma omp atomic
check4[id] += check4Inc;
}
}
}
// CHECK: target: level = 0, activeLevel = 0
printf("target: level = %d, activeLevel = %d\n", level, activeLevel);
// CHECK: level = -1: ancestorTNum = -1, teamSize = -1
printf("level = -1: ancestorTNum = %d, teamSize = %d\n", ancestorTNumNeg, teamSizeNeg);
// CHECK: level = 0: ancestorTNum = 0, teamSize = 1
printf("level = 0: ancestorTNum = %d, teamSize = %d\n", ancestorTNum0, teamSize0);
// CHECK: level = 1: ancestorTNum = -1, teamSize = -1
printf("level = 1: ancestorTNum = %d, teamSize = %d\n", ancestorTNum1, teamSize1);
// CHECK-NOT: invalid
for (int i = 0; i < MaxThreads; i++) {
// Check active parallel region:
// omp_get_level() = 1, omp_get_active_level() = 1
const int Expected1 = 6;
if (i < NumThreads) {
if (check1[i] != Expected1) {
printf("invalid: check1[%d] should be %d, is %d\n", i, Expected1, check1[i]);
}
} else if (check1[i] != 0) {
printf("invalid: check1[%d] should be 0, is %d\n", i, check1[i]);
}
// 5 * 1 + 3 * 64 - 1 - 1 (see above)
const int Expected2 = 195;
if (i < NumThreads) {
if (check2[i] != Expected2) {
printf("invalid: check2[%d] should be %d, is %d\n", i, Expected2, check2[i]);
}
} else if (check2[i] != 0) {
printf("invalid: check2[%d] should be 0, is %d\n", i, check2[i]);
}
// Check serialized parallel region:
// omp_get_level() = 2, omp_get_active_level() = 1
const int Expected3 = 11;
if (i < NumThreads) {
if (check3[i] != Expected3) {
printf("invalid: check3[%d] should be %d, is %d\n", i, Expected3, check3[i]);
}
} else if (check3[i] != 0) {
printf("invalid: check3[%d] should be 0, is %d\n", i, check3[i]);
}
// 5 * 1 + 3 * 64 + 3 * 1 - 1 - 1 (see above)
const int Expected4 = 198;
if (i < NumThreads) {
if (check4[i] != Expected4) {
printf("invalid: check4[%d] should be %d, is %d\n", i, Expected4, check4[i]);
}
} else if (check4[i] != 0) {
printf("invalid: check4[%d] should be 0, is %d\n", i, check4[i]);
}
}
// Check for paraller level in non-SPMD kernels.
level = 0;
#pragma omp target teams distribute num_teams(1) thread_limit(32) reduction(+:level)
for (int i=0; i<5032; i+=32) {
int ub = (i+32 > 5032) ? 5032 : i+32;
#pragma omp parallel for schedule(dynamic)
for (int j=i ; j < ub; j++) ;
level += omp_get_level();
}
// CHECK: Integral level = 0.
printf("Integral level = %d.\n", level);
return 0;
}
@@ -0,0 +1,136 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
const int MaxThreads = 1024;
const int NumThreads = 64;
const int NumThreads1 = 1;
int main(int argc, char *argv[]) {
int inParallel = -1, numThreads = -1, threadNum = -1;
int check1[MaxThreads];
int check2[MaxThreads];
for (int i = 0; i < MaxThreads; i++) {
check1[i] = check2[i] = 0;
}
#pragma omp target map(inParallel, numThreads, threadNum, check1[:], check2[:])
{
inParallel = omp_in_parallel();
numThreads = omp_get_num_threads();
threadNum = omp_get_thread_num();
// Expecting active parallel region.
#pragma omp parallel num_threads(NumThreads)
{
int id = omp_get_thread_num();
check1[id] += omp_get_num_threads() + omp_in_parallel();
// Expecting serialized parallel region.
#pragma omp parallel
{
// Expected to be 1.
int nestedInParallel = omp_in_parallel();
// Expected to be 1.
int nestedNumThreads = omp_get_num_threads();
// Expected to be 0.
int nestedThreadNum = omp_get_thread_num();
#pragma omp atomic
check2[id] += nestedInParallel + nestedNumThreads + nestedThreadNum;
}
}
}
// CHECK: target: inParallel = 0, numThreads = 1, threadNum = 0
printf("target: inParallel = %d, numThreads = %d, threadNum = %d\n",
inParallel, numThreads, threadNum);
// CHECK-NOT: invalid
for (int i = 0; i < MaxThreads; i++) {
// Check that all threads reported
// omp_get_num_threads() = 64, omp_in_parallel() = 1.
int Expected = NumThreads + 1;
if (i < NumThreads) {
if (check1[i] != Expected) {
printf("invalid: check1[%d] should be %d, is %d\n", i, Expected,
check1[i]);
}
} else if (check1[i] != 0) {
printf("invalid: check1[%d] should be 0, is %d\n", i, check1[i]);
}
// Check serialized parallel region.
if (i < NumThreads) {
if (check2[i] != 2) {
printf("invalid: check2[%d] should be 2, is %d\n", i, check2[i]);
}
} else if (check2[i] != 0) {
printf("invalid: check2[%d] should be 0, is %d\n", i, check2[i]);
}
}
inParallel = -1;
numThreads = -1;
threadNum = -1;
for (int i = 0; i < MaxThreads; i++) {
check1[i] = check2[i] = 0;
}
#pragma omp target map(inParallel, numThreads, threadNum, check1[:], check2[:])
{
inParallel = omp_in_parallel();
numThreads = omp_get_num_threads();
threadNum = omp_get_thread_num();
// Expecting active parallel region.
#pragma omp parallel num_threads(NumThreads1)
{
int id = omp_get_thread_num();
check1[id] += omp_get_num_threads() + omp_in_parallel();
// Expecting serialized parallel region.
#pragma omp parallel
{
// Expected to be 0.
int nestedInParallel = omp_in_parallel();
// Expected to be 1.
int nestedNumThreads = omp_get_num_threads();
// Expected to be 0.
int nestedThreadNum = omp_get_thread_num();
#pragma omp atomic
check2[id] += nestedInParallel + nestedNumThreads + nestedThreadNum;
}
}
}
// CHECK: target: inParallel = 0, numThreads = 1, threadNum = 0
printf("target: inParallel = %d, numThreads = %d, threadNum = %d\n",
inParallel, numThreads, threadNum);
// CHECK-NOT: invalid
for (int i = 0; i < MaxThreads; i++) {
// Check that all threads reported
// omp_get_num_threads() = 1, omp_in_parallel() = 0.
int Expected = 1;
if (i < NumThreads1) {
if (check1[i] != Expected) {
printf("invalid: check1[%d] should be %d, is %d\n", i, Expected,
check1[i]);
}
} else if (check1[i] != 0) {
printf("invalid: check1[%d] should be 0, is %d\n", i, check1[i]);
}
// Check serialized parallel region.
if (i < NumThreads1) {
if (check2[i] != 1) {
printf("invalid: check2[%d] should be 1, is %d\n", i, check2[i]);
}
} else if (check2[i] != 0) {
printf("invalid: check2[%d] should be 0, is %d\n", i, check2[i]);
}
}
return 0;
}
@@ -0,0 +1,102 @@
// RUN: %compile-run-and-check
#include <stdio.h>
#include <omp.h>
const int WarpSize = 32;
const int NumThreads1 = 1 * WarpSize;
const int NumThreads2 = 2 * WarpSize;
const int NumThreads3 = 3 * WarpSize;
const int MaxThreads = 1024;
int main(int argc, char *argv[]) {
int check1[MaxThreads];
int check2[MaxThreads];
int check3[MaxThreads];
int check4[MaxThreads];
for (int i = 0; i < MaxThreads; i++) {
check1[i] = check2[i] = check3[i] = check4[i] = 0;
}
int maxThreads1 = -1;
int maxThreads2 = -1;
int maxThreads3 = -1;
#pragma omp target map(check1[:], check2[:], check3[:], check4[:]) \
map(maxThreads1, maxThreads2, maxThreads3)
{
#pragma omp parallel num_threads(NumThreads1)
{
check1[omp_get_thread_num()] += omp_get_num_threads();
}
// API method to set number of threads in parallel regions without
// num_threads() clause.
omp_set_num_threads(NumThreads2);
maxThreads1 = omp_get_max_threads();
#pragma omp parallel
{
check2[omp_get_thread_num()] += omp_get_num_threads();
}
maxThreads2 = omp_get_max_threads();
// num_threads() clause should override nthreads-var ICV.
#pragma omp parallel num_threads(NumThreads3)
{
check3[omp_get_thread_num()] += omp_get_num_threads();
}
maxThreads3 = omp_get_max_threads();
// Effect from omp_set_num_threads() should still be visible.
#pragma omp parallel
{
check4[omp_get_thread_num()] += omp_get_num_threads();
}
}
// CHECK: maxThreads1 = 64
printf("maxThreads1 = %d\n", maxThreads1);
// CHECK: maxThreads2 = 64
printf("maxThreads2 = %d\n", maxThreads2);
// CHECK: maxThreads3 = 64
printf("maxThreads3 = %d\n", maxThreads3);
// CHECK-NOT: invalid
for (int i = 0; i < MaxThreads; i++) {
if (i < NumThreads1) {
if (check1[i] != NumThreads1) {
printf("invalid: check1[%d] should be %d, is %d\n", i, NumThreads1, check1[i]);
}
} else if (check1[i] != 0) {
printf("invalid: check1[%d] should be 0, is %d\n", i, check1[i]);
}
if (i < NumThreads2) {
if (check2[i] != NumThreads2) {
printf("invalid: check2[%d] should be %d, is %d\n", i, NumThreads2, check2[i]);
}
} else if (check2[i] != 0) {
printf("invalid: check2[%d] should be 0, is %d\n", i, check2[i]);
}
if (i < NumThreads3) {
if (check3[i] != NumThreads3) {
printf("invalid: check3[%d] should be %d, is %d\n", i, NumThreads3, check3[i]);
}
} else if (check3[i] != 0) {
printf("invalid: check3[%d] should be 0, is %d\n", i, check3[i]);
}
if (i < NumThreads2) {
if (check4[i] != NumThreads2) {
printf("invalid: check4[%d] should be %d, is %d\n", i, NumThreads2, check4[i]);
}
} else if (check4[i] != 0) {
printf("invalid: check4[%d] should be 0, is %d\n", i, check4[i]);
}
}
return 0;
}
@@ -0,0 +1,51 @@
// RUN: %compilexx-run-and-check
#include <stdio.h>
#include <omp.h>
int main(void) {
int isHost = -1;
int ParallelLevel1 = -1, ParallelLevel2 = -1;
int Count = 0;
#pragma omp target parallel for map(tofrom \
: isHost, ParallelLevel1, ParallelLevel2), reduction(+: Count) schedule(static, 1)
for (int J = 0; J < 10; ++J) {
#pragma omp critical
{
isHost = (isHost < 0 || isHost == 0) ? omp_is_initial_device() : isHost;
ParallelLevel1 = (ParallelLevel1 < 0 || ParallelLevel1 == 1)
? omp_get_level()
: ParallelLevel1;
}
if (omp_get_thread_num() > 5) {
int L2;
#pragma omp parallel for schedule(dynamic) lastprivate(L2) reduction(+: Count)
for (int I = 0; I < 10; ++I) {
L2 = omp_get_level();
Count += omp_get_level(); // (10-6)*10*2 = 80
}
#pragma omp critical
ParallelLevel2 =
(ParallelLevel2 < 0 || ParallelLevel2 == 2) ? L2 : ParallelLevel2;
} else {
Count += omp_get_level(); // 6 * 1 = 6
}
}
if (isHost < 0) {
printf("Runtime error, isHost=%d\n", isHost);
}
// CHECK: Target region executed on the device
printf("Target region executed on the %s\n", isHost ? "host" : "device");
// CHECK: Parallel level in SPMD mode: L1 is 1, L2 is 2
printf("Parallel level in SPMD mode: L1 is %d, L2 is %d\n", ParallelLevel1,
ParallelLevel2);
// Final result of Count is (10-6)(num of loops)*10(num of iterations)*2(par
// level) + 6(num of iterations) * 1(par level)
// CHECK: Expected count = 86
printf("Expected count = %d\n", Count);
return isHost;
}
@@ -0,0 +1,77 @@
// RUN: %compile-run-and-check
#include <stdio.h>
#include <omp.h>
const int WarpSize = 32;
const int ThreadLimit = 1 * WarpSize;
const int NumThreads2 = 2 * WarpSize;
const int NumThreads3 = 3 * WarpSize;
const int MaxThreads = 1024;
int main(int argc, char *argv[]) {
int check1[MaxThreads];
int check2[MaxThreads];
int check3[MaxThreads];
for (int i = 0; i < MaxThreads; i++) {
check1[i] = check2[i] = check3[i] = 0;
}
int threadLimit = -1;
#pragma omp target teams num_teams(1) thread_limit(ThreadLimit) \
map(check1[:], check2[:], check3[:], threadLimit)
{
threadLimit = omp_get_thread_limit();
// All parallel regions should get as many threads as specified by the
// thread_limit() clause.
#pragma omp parallel
{
check1[omp_get_thread_num()] += omp_get_num_threads();
}
omp_set_num_threads(NumThreads2);
#pragma omp parallel
{
check2[omp_get_thread_num()] += omp_get_num_threads();
}
#pragma omp parallel num_threads(NumThreads3)
{
check3[omp_get_thread_num()] += omp_get_num_threads();
}
}
// CHECK: threadLimit = 32
printf("threadLimit = %d\n", threadLimit);
// CHECK-NOT: invalid
for (int i = 0; i < MaxThreads; i++) {
if (i < ThreadLimit) {
if (check1[i] != ThreadLimit) {
printf("invalid: check1[%d] should be %d, is %d\n", i, ThreadLimit, check1[i]);
}
} else if (check1[i] != 0) {
printf("invalid: check1[%d] should be 0, is %d\n", i, check1[i]);
}
if (i < ThreadLimit) {
if (check2[i] != ThreadLimit) {
printf("invalid: check2[%d] should be %d, is %d\n", i, ThreadLimit, check2[i]);
}
} else if (check2[i] != 0) {
printf("invalid: check2[%d] should be 0, is %d\n", i, check2[i]);
}
if (i < ThreadLimit) {
if (check3[i] != ThreadLimit) {
printf("invalid: check3[%d] should be %d, is %d\n", i, ThreadLimit, check3[i]);
}
} else if (check3[i] != 0) {
printf("invalid: check3[%d] should be 0, is %d\n", i, check3[i]);
}
}
return 0;
}
@@ -0,0 +1,22 @@
// RUN: %compile-run-and-check
#include <omp.h>
#include <stdio.h>
int main() {
int res = 0;
#pragma omp parallel num_threads(2) reduction(+:res)
{
int tid = omp_get_thread_num();
#pragma omp target teams distribute reduction(+:res)
for (int i = tid; i < 2; i++)
++res;
}
// The first thread makes 2 iterations, the second - 1. Expected result of the
// reduction res is 3.
// CHECK: res = 3.
printf("res = %d.\n", res);
return 0;
}
+23 -4
View File
@@ -1,9 +1,8 @@
//===-------- omptarget.h - Target independent OpenMP target RTL -- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -48,6 +47,8 @@ enum tgt_map_type {
OMP_TGT_MAPTYPE_LITERAL = 0x100,
// mapping is implicit
OMP_TGT_MAPTYPE_IMPLICIT = 0x200,
// copy data to device
OMP_TGT_MAPTYPE_CLOSE = 0x400,
// member of struct, member given by [16 MSBs] - 1
OMP_TGT_MAPTYPE_MEMBER_OF = 0xffff000000000000
};
@@ -61,6 +62,21 @@ enum OpenMPOffloadingDeclareTargetFlags {
OMP_DECLARE_TARGET_DTOR = 0x04
};
enum OpenMPOffloadingRequiresDirFlags {
/// flag undefined.
OMP_REQ_UNDEFINED = 0x000,
/// no requires directive present.
OMP_REQ_NONE = 0x001,
/// reverse_offload clause.
OMP_REQ_REVERSE_OFFLOAD = 0x002,
/// unified_address clause.
OMP_REQ_UNIFIED_ADDRESS = 0x004,
/// unified_shared_memory clause.
OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
/// dynamic_allocators clause.
OMP_REQ_DYNAMIC_ALLOCATORS = 0x010
};
/// This struct is a record of an entry point or global. For a function
/// entry point the size is expected to be zero
struct __tgt_offload_entry {
@@ -114,6 +130,9 @@ int omp_target_associate_ptr(void *host_ptr, void *device_ptr, size_t size,
size_t device_offset, int device_num);
int omp_target_disassociate_ptr(void *host_ptr, int device_num);
/// add the clauses of the requires directives in a given file
void __tgt_register_requires(int64_t flags);
/// adds a target shared library to the target execution image
void __tgt_register_lib(__tgt_bin_desc *desc);
+6 -4
View File
@@ -1,9 +1,8 @@
//===-- omptargetplugin.h - Target dependent OpenMP Plugin API --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -32,6 +31,9 @@ int32_t __tgt_rtl_number_of_devices(void);
// having to load the library, which can be expensive.
int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image);
// Initialize the requires flags for the device.
int64_t __tgt_rtl_init_requires(int64_t RequiresFlags);
// Initialize the specified device. In case of success return 0; otherwise
// return an error code.
int32_t __tgt_rtl_init_device(int32_t ID);
+3 -4
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
+3 -4
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
+3 -4
View File
@@ -1,9 +1,8 @@
//===-- elf_common.c - Common ELF functionality -------------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
+3 -8
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
@@ -29,10 +28,6 @@ libomptarget_say("Building CUDA offloading plugin.")
# Define the suffix for the runtime messaging dumps.
add_definitions(-DTARGET_NAME=CUDA)
if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
add_definitions(-DCUDA_ERROR_REPORT)
endif()
include_directories(${LIBOMPTARGET_DEP_CUDA_INCLUDE_DIRS})
include_directories(${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIRS})
+83 -49
View File
@@ -1,9 +1,8 @@
//===----RTLs/cuda/src/rtl.cpp - Target RTLs Implementation ------- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -35,25 +34,23 @@ static int DebugLevel = 0;
DEBUGP("Target " GETNAME(TARGET_NAME) " RTL", __VA_ARGS__); \
} \
} while (false)
// Utility for retrieving and printing CUDA error string.
#define CUDA_ERR_STRING(err) \
do { \
if (DebugLevel > 0) { \
const char *errStr; \
cuGetErrorString(err, &errStr); \
DEBUGP("Target " GETNAME(TARGET_NAME) " RTL", "CUDA error is: %s\n", errStr); \
} \
} while (false)
#else // OMPTARGET_DEBUG
#define DP(...) {}
#define CUDA_ERR_STRING(err) {}
#endif // OMPTARGET_DEBUG
#include "../../common/elf_common.c"
// Utility for retrieving and printing CUDA error string.
#ifdef CUDA_ERROR_REPORT
#define CUDA_ERR_STRING(err) \
do { \
const char *errStr; \
cuGetErrorString(err, &errStr); \
DP("CUDA error is: %s\n", errStr); \
} while (0)
#else
#define CUDA_ERR_STRING(err) \
{}
#endif
/// Keep entries table per device.
struct FuncOrGblEntryTy {
__tgt_target_table Table;
@@ -112,6 +109,9 @@ public:
int EnvNumTeams;
int EnvTeamLimit;
// OpenMP Requires Flags
int64_t RequiresFlags;
//static int EnvNumThreads;
static const int HardTeamLimit = 1<<16; // 64k
static const int HardThreadLimit = 1024;
@@ -228,6 +228,9 @@ public:
} else {
EnvNumTeams = -1;
}
// Default state.
RequiresFlags = OMP_REQ_UNDEFINED;
}
~RTLDeviceInfoTy() {
@@ -265,6 +268,12 @@ int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *image) {
int32_t __tgt_rtl_number_of_devices() { return DeviceInfo.NumberOfDevices; }
int64_t __tgt_rtl_init_requires(int64_t RequiresFlags) {
DP("Init requires flags to %ld\n", RequiresFlags);
DeviceInfo.RequiresFlags = RequiresFlags;
return RequiresFlags;
}
int32_t __tgt_rtl_init_device(int32_t device_id) {
CUdevice cuDevice;
@@ -285,43 +294,48 @@ int32_t __tgt_rtl_init_device(int32_t device_id) {
return OFFLOAD_FAIL;
}
// scan properties to determine number of threads/block and blocks/grid.
CUdevprop Properties;
err = cuDeviceGetProperties(&Properties, cuDevice);
// Query attributes to determine number of threads/block and blocks/grid.
int maxGridDimX;
err = cuDeviceGetAttribute(&maxGridDimX, CU_DEVICE_ATTRIBUTE_MAX_GRID_DIM_X,
cuDevice);
if (err != CUDA_SUCCESS) {
DP("Error getting device Properties, use defaults\n");
DP("Error getting max grid dimension, use default\n");
DeviceInfo.BlocksPerGrid[device_id] = RTLDeviceInfoTy::DefaultNumTeams;
} else if (maxGridDimX <= RTLDeviceInfoTy::HardTeamLimit) {
DeviceInfo.BlocksPerGrid[device_id] = maxGridDimX;
DP("Using %d CUDA blocks per grid\n", maxGridDimX);
} else {
DeviceInfo.BlocksPerGrid[device_id] = RTLDeviceInfoTy::HardTeamLimit;
DP("Max CUDA blocks per grid %d exceeds the hard team limit %d, capping "
"at the hard limit\n",
maxGridDimX, RTLDeviceInfoTy::HardTeamLimit);
}
// We are only exploiting threads along the x axis.
int maxBlockDimX;
err = cuDeviceGetAttribute(&maxBlockDimX, CU_DEVICE_ATTRIBUTE_MAX_BLOCK_DIM_X,
cuDevice);
if (err != CUDA_SUCCESS) {
DP("Error getting max block dimension, use default\n");
DeviceInfo.ThreadsPerBlock[device_id] = RTLDeviceInfoTy::DefaultNumThreads;
} else if (maxBlockDimX <= RTLDeviceInfoTy::HardThreadLimit) {
DeviceInfo.ThreadsPerBlock[device_id] = maxBlockDimX;
DP("Using %d CUDA threads per block\n", maxBlockDimX);
} else {
DeviceInfo.ThreadsPerBlock[device_id] = RTLDeviceInfoTy::HardThreadLimit;
DP("Max CUDA threads per block %d exceeds the hard thread limit %d, capping"
"at the hard limit\n",
maxBlockDimX, RTLDeviceInfoTy::HardThreadLimit);
}
int warpSize;
err =
cuDeviceGetAttribute(&warpSize, CU_DEVICE_ATTRIBUTE_WARP_SIZE, cuDevice);
if (err != CUDA_SUCCESS) {
DP("Error getting warp size, assume default\n");
DeviceInfo.WarpSize[device_id] = 32;
} else {
// Get blocks per grid
if (Properties.maxGridSize[0] <= RTLDeviceInfoTy::HardTeamLimit) {
DeviceInfo.BlocksPerGrid[device_id] = Properties.maxGridSize[0];
DP("Using %d CUDA blocks per grid\n", Properties.maxGridSize[0]);
} else {
DeviceInfo.BlocksPerGrid[device_id] = RTLDeviceInfoTy::HardTeamLimit;
DP("Max CUDA blocks per grid %d exceeds the hard team limit %d, capping "
"at the hard limit\n", Properties.maxGridSize[0],
RTLDeviceInfoTy::HardTeamLimit);
}
// Get threads per block, exploit threads only along x axis
if (Properties.maxThreadsDim[0] <= RTLDeviceInfoTy::HardThreadLimit) {
DeviceInfo.ThreadsPerBlock[device_id] = Properties.maxThreadsDim[0];
DP("Using %d CUDA threads per block\n", Properties.maxThreadsDim[0]);
if (Properties.maxThreadsDim[0] < Properties.maxThreadsPerBlock) {
DP("(fewer than max per block along all xyz dims %d)\n",
Properties.maxThreadsPerBlock);
}
} else {
DeviceInfo.ThreadsPerBlock[device_id] = RTLDeviceInfoTy::HardThreadLimit;
DP("Max CUDA threads per block %d exceeds the hard thread limit %d, "
"capping at the hard limit\n", Properties.maxThreadsDim[0],
RTLDeviceInfoTy::HardThreadLimit);
}
// According to the documentation, SIMDWidth is "Warp size in threads".
DeviceInfo.WarpSize[device_id] = Properties.SIMDWidth;
DeviceInfo.WarpSize[device_id] = warpSize;
}
// Adjust teams to the env variables
@@ -432,6 +446,26 @@ __tgt_target_table *__tgt_rtl_load_binary(int32_t device_id,
DPxPTR(e - HostBegin), e->name, DPxPTR(cuptr));
entry.addr = (void *)cuptr;
// Note: In the current implementation declare target variables
// can either be link or to. This means that once unified
// memory is activated via the requires directive, the variable
// can be used directly from the host in both cases.
// TODO: when variables types other than to or link are added,
// the below condition should be changed to explicitely
// check for to and link variables types:
// (DeviceInfo.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
// (e->flags & OMP_DECLARE_TARGET_LINK ||
// e->flags == OMP_DECLARE_TARGET_TO))
if (DeviceInfo.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) {
// If unified memory is present any target link or to variables
// can access host addresses directly. There is no longer a
// need for device copies.
cuMemcpyHtoD(cuptr, e->addr, sizeof(void *));
DP("Copy linked variable host address (" DPxMOD ")"
"to device address (" DPxMOD ")\n",
DPxPTR(*((void**)e->addr)), DPxPTR(cuptr));
}
DeviceInfo.addOffloadEntry(device_id, entry);
continue;
+1
View File
@@ -2,6 +2,7 @@ VERS1.0 {
global:
__tgt_rtl_is_valid_binary;
__tgt_rtl_number_of_devices;
__tgt_rtl_init_requires;
__tgt_rtl_init_device;
__tgt_rtl_load_binary;
__tgt_rtl_data_alloc;
@@ -1,9 +1,8 @@
//===-RTLs/generic-64bit/src/rtl.cpp - Target RTLs Implementation - C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -51,7 +50,7 @@ static int DebugLevel = 0;
#include "../../common/elf_common.c"
#define NUMBER_OF_DEVICES 4
#define OFFLOADSECTIONNAME ".omp_offloading.entries"
#define OFFLOADSECTIONNAME "omp_offloading_entries"
/// Array of Dynamic libraries loaded for this target.
struct DynLibTy {
+3 -4
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
+3 -4
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
+3 -4
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
+5 -5
View File
@@ -1,9 +1,8 @@
##===----------------------------------------------------------------------===##
#
# The LLVM Compiler Infrastructure
#
# This file is dual licensed under the MIT and the University of Illinois Open
# Source Licenses. See LICENSE.txt for details.
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##
#
@@ -28,4 +27,5 @@ target_link_libraries(omptarget
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/exports")
# Install libomptarget under the lib destination folder.
install(TARGETS omptarget LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}")
install(TARGETS omptarget LIBRARY COMPONENT omptarget
DESTINATION "${OPENMP_INSTALL_LIBDIR}")
+12 -5
View File
@@ -1,9 +1,8 @@
//===----------- api.cpp - Target independent OpenMP target RTL -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -114,7 +113,15 @@ EXTERN int omp_target_is_present(void *ptr, int device_num) {
DeviceTy& Device = Devices[device_num];
bool IsLast; // not used
int rc = (Device.getTgtPtrBegin(ptr, 0, IsLast, false) != NULL);
bool IsHostPtr;
void *TgtPtr = Device.getTgtPtrBegin(ptr, 0, IsLast, false, IsHostPtr);
int rc = (TgtPtr != NULL);
// Under unified memory the host pointer can be returned by the
// getTgtPtrBegin() function which means that there is no device
// corresponding point for ptr. This function should return false
// in that situation.
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY)
rc = !IsHostPtr;
DP("Call to omp_target_is_present returns %d\n", rc);
return rc;
}
+50 -19
View File
@@ -1,9 +1,8 @@
//===--------- device.cpp - Target independent OpenMP target RTL ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -153,17 +152,22 @@ LookupResult DeviceTy::lookupMapping(void *HstPtrBegin, int64_t Size) {
// Used by target_data_begin
// Return the target pointer begin (where the data will be moved).
// Allocate memory if this is the first occurrence if this mapping.
// Allocate memory if this is the first occurrence of this mapping.
// Increment the reference counter.
// If NULL is returned, then either data allocation failed or the user tried
// to do an illegal mapping.
void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
int64_t Size, bool &IsNew, bool IsImplicit, bool UpdateRefCount) {
int64_t Size, bool &IsNew, bool &IsHostPtr, bool IsImplicit,
bool UpdateRefCount, bool HasCloseModifier) {
void *rc = NULL;
IsHostPtr = false;
DataMapMtx.lock();
LookupResult lr = lookupMapping(HstPtrBegin, Size);
// Check if the pointer is contained.
// If a variable is mapped to the device manually by the user - which would
// lead to the IsContained flag to be true - then we must ensure that the
// device address is returned even under unified memory conditions.
if (lr.Flags.IsContained ||
((lr.Flags.ExtendsBefore || lr.Flags.ExtendsAfter) && IsImplicit)) {
auto &HT = *lr.Entry;
@@ -184,15 +188,28 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
// Explicit extension of mapped data - not allowed.
DP("Explicit extension of mapping is not allowed.\n");
} else if (Size) {
// If it is not contained and Size > 0 we should create a new entry for it.
IsNew = true;
uintptr_t tp = (uintptr_t)RTL->data_alloc(RTLDeviceID, Size, HstPtrBegin);
DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD ", "
"HstEnd=" DPxMOD ", TgtBegin=" DPxMOD "\n", DPxPTR(HstPtrBase),
DPxPTR(HstPtrBegin), DPxPTR((uintptr_t)HstPtrBegin + Size), DPxPTR(tp));
HostDataToTargetMap.push_front(HostDataToTargetTy((uintptr_t)HstPtrBase,
(uintptr_t)HstPtrBegin, (uintptr_t)HstPtrBegin + Size, tp));
rc = (void *)tp;
// If unified shared memory is active, implicitly mapped variables that are not
// privatized use host address. Any explicitly mapped variables also use
// host address where correctness is not impeded. In all other cases
// maps are respected.
// In addition to the mapping rules above, the close map
// modifier forces the mapping of the variable to the device.
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && !HasCloseModifier) {
DP("Return HstPtrBegin " DPxMOD " Size=%ld RefCount=%s\n",
DPxPTR((uintptr_t)HstPtrBegin), Size, (UpdateRefCount ? " updated" : ""));
IsHostPtr = true;
rc = HstPtrBegin;
} else {
// If it is not contained and Size > 0 we should create a new entry for it.
IsNew = true;
uintptr_t tp = (uintptr_t)RTL->data_alloc(RTLDeviceID, Size, HstPtrBegin);
DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD ", "
"HstEnd=" DPxMOD ", TgtBegin=" DPxMOD "\n", DPxPTR(HstPtrBase),
DPxPTR(HstPtrBegin), DPxPTR((uintptr_t)HstPtrBegin + Size), DPxPTR(tp));
HostDataToTargetMap.push_front(HostDataToTargetTy((uintptr_t)HstPtrBase,
(uintptr_t)HstPtrBegin, (uintptr_t)HstPtrBegin + Size, tp));
rc = (void *)tp;
}
}
DataMapMtx.unlock();
@@ -203,8 +220,10 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
// Return the target pointer begin (where the data will be moved).
// Decrement the reference counter if called from target_data_end.
void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
bool UpdateRefCount) {
bool UpdateRefCount, bool &IsHostPtr) {
void *rc = NULL;
IsHostPtr = false;
IsLast = false;
DataMapMtx.lock();
LookupResult lr = lookupMapping(HstPtrBegin, Size);
@@ -222,8 +241,14 @@ void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
(CONSIDERED_INF(HT.RefCount)) ? "INF" :
std::to_string(HT.RefCount).c_str());
rc = (void *)tp;
} else {
IsLast = false;
} else if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) {
// If the value isn't found in the mapping and unified shared memory
// is on then it means we have stumbled upon a value which we need to
// use directly from the host.
DP("Get HstPtrBegin " DPxMOD " Size=%ld RefCount=%s\n",
DPxPTR((uintptr_t)HstPtrBegin), Size, (UpdateRefCount ? " updated" : ""));
IsHostPtr = true;
rc = HstPtrBegin;
}
DataMapMtx.unlock();
@@ -244,7 +269,10 @@ void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size) {
return NULL;
}
int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete) {
int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete,
bool HasCloseModifier) {
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && !HasCloseModifier)
return OFFLOAD_SUCCESS;
// Check if the pointer is contained in any sub-nodes.
int rc;
DataMapMtx.lock();
@@ -276,6 +304,9 @@ int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete) {
/// Init device, should not be called directly.
void DeviceTy::init() {
// Make call to init_requires if it exists for this plugin.
if (RTL->init_requires)
RTL->init_requires(RTLs.RequiresFlags);
int32_t rc = RTL->init_device(RTLDeviceID);
if (rc == OFFLOAD_SUCCESS) {
IsInit = true;
+16 -14
View File
@@ -1,9 +1,8 @@
//===----------- device.h - Target independent OpenMP target RTL ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -97,13 +96,14 @@ struct DeviceTy {
std::mutex DataMapMtx, PendingGlobalsMtx, ShadowMtx;
uint64_t loopTripCnt;
// NOTE: Once libomp gains full target-task support, this state should be
// moved into the target task in libomp.
std::map<int32_t, uint64_t> LoopTripCnt;
DeviceTy(RTLInfoTy *RTL)
: DeviceID(-1), RTL(RTL), RTLDeviceID(-1), IsInit(false), InitFlag(),
HasPendingGlobals(false), HostDataToTargetMap(),
PendingCtorsDtors(), ShadowPtrMap(), DataMapMtx(), PendingGlobalsMtx(),
ShadowMtx(), loopTripCnt(0) {}
HasPendingGlobals(false), HostDataToTargetMap(), PendingCtorsDtors(),
ShadowPtrMap(), DataMapMtx(), PendingGlobalsMtx(), ShadowMtx() {}
// The existence of mutexes makes DeviceTy non-copyable. We need to
// provide a copy constructor and an assignment operator explicitly.
@@ -112,8 +112,8 @@ struct DeviceTy {
IsInit(d.IsInit), InitFlag(), HasPendingGlobals(d.HasPendingGlobals),
HostDataToTargetMap(d.HostDataToTargetMap),
PendingCtorsDtors(d.PendingCtorsDtors), ShadowPtrMap(d.ShadowPtrMap),
DataMapMtx(), PendingGlobalsMtx(),
ShadowMtx(), loopTripCnt(d.loopTripCnt) {}
DataMapMtx(), PendingGlobalsMtx(), ShadowMtx(),
LoopTripCnt(d.LoopTripCnt) {}
DeviceTy& operator=(const DeviceTy &d) {
DeviceID = d.DeviceID;
@@ -124,7 +124,7 @@ struct DeviceTy {
HostDataToTargetMap = d.HostDataToTargetMap;
PendingCtorsDtors = d.PendingCtorsDtors;
ShadowPtrMap = d.ShadowPtrMap;
loopTripCnt = d.loopTripCnt;
LoopTripCnt = d.LoopTripCnt;
return *this;
}
@@ -132,11 +132,13 @@ struct DeviceTy {
long getMapEntryRefCnt(void *HstPtrBegin);
LookupResult lookupMapping(void *HstPtrBegin, int64_t Size);
void *getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase, int64_t Size,
bool &IsNew, bool IsImplicit, bool UpdateRefCount = true);
bool &IsNew, bool &IsHostPtr, bool IsImplicit, bool UpdateRefCount = true,
bool HasCloseModifier = false);
void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size);
void *getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
bool UpdateRefCount);
int deallocTgtPtr(void *TgtPtrBegin, int64_t Size, bool ForceDelete);
bool UpdateRefCount, bool &IsHostPtr);
int deallocTgtPtr(void *TgtPtrBegin, int64_t Size, bool ForceDelete,
bool HasCloseModifier = false);
int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);
int disassociatePtr(void *HstPtrBegin);
+3
View File
@@ -1,5 +1,6 @@
VERS1.0 {
global:
__tgt_register_requires;
__tgt_register_lib;
__tgt_unregister_lib;
__tgt_target_data_begin;
@@ -12,6 +13,8 @@ VERS1.0 {
__tgt_target_data_update_nowait;
__tgt_target_nowait;
__tgt_target_teams_nowait;
__tgt_mapper_num_components;
__tgt_push_mapper_component;
omp_get_num_devices;
omp_get_initial_device;
omp_target_alloc;
+114 -15
View File
@@ -1,9 +1,8 @@
//===-------- interface.cpp - Target independent OpenMP target RTL --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -20,6 +19,60 @@
#include <cassert>
#include <cstdlib>
#include <mutex>
// Store target policy (disabled, mandatory, default)
kmp_target_offload_kind_t TargetOffloadPolicy = tgt_default;
std::mutex TargetOffloadMtx;
////////////////////////////////////////////////////////////////////////////////
/// manage the success or failure of a target constuct
static void HandleDefaultTargetOffload() {
TargetOffloadMtx.lock();
if (TargetOffloadPolicy == tgt_default) {
if (omp_get_num_devices() > 0) {
DP("Default TARGET OFFLOAD policy is now mandatory "
"(devices were found)\n");
TargetOffloadPolicy = tgt_mandatory;
} else {
DP("Default TARGET OFFLOAD policy is now disabled "
"(no devices were found)\n");
TargetOffloadPolicy = tgt_disabled;
}
}
TargetOffloadMtx.unlock();
}
static int IsOffloadDisabled() {
if (TargetOffloadPolicy == tgt_default) HandleDefaultTargetOffload();
return TargetOffloadPolicy == tgt_disabled;
}
static void HandleTargetOutcome(bool success) {
switch (TargetOffloadPolicy) {
case tgt_disabled:
if (success) {
FATAL_MESSAGE0(1, "expected no offloading while offloading is disabled");
}
break;
case tgt_default:
FATAL_MESSAGE0(1, "default offloading policy must be switched to "
"mandatory or disabled");
break;
case tgt_mandatory:
if (!success) {
FATAL_MESSAGE0(1, "failure of target construct while offloading is mandatory");
}
break;
}
}
////////////////////////////////////////////////////////////////////////////////
/// adds requires flags
EXTERN void __tgt_register_requires(int64_t flags) {
RTLs.RegisterRequires(flags);
}
////////////////////////////////////////////////////////////////////////////////
/// adds a target shared library to the target execution image
@@ -38,6 +91,8 @@ EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) {
/// and passes the data to the device.
EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
if (IsOffloadDisabled()) return;
DP("Entering data begin region for device %" PRId64 " with %d mappings\n",
device_id, arg_num);
@@ -49,6 +104,7 @@ EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %" PRId64 " ready\n", device_id);
HandleTargetOutcome(false);
return;
}
@@ -62,7 +118,9 @@ EXTERN void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
}
#endif
target_data_begin(Device, arg_num, args_base, args, arg_sizes, arg_types);
int rc = target_data_begin(Device, arg_num, args_base,
args, arg_sizes, arg_types);
HandleTargetOutcome(rc == OFFLOAD_SUCCESS);
}
EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
@@ -70,7 +128,7 @@ EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
__tgt_target_data_begin(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
@@ -81,6 +139,7 @@ EXTERN void __tgt_target_data_begin_nowait(int64_t device_id, int32_t arg_num,
/// created by the last __tgt_target_data_begin.
EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
if (IsOffloadDisabled()) return;
DP("Entering data end region with %d mappings\n", arg_num);
// No devices available?
@@ -93,12 +152,14 @@ EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
RTLsMtx.unlock();
if (Devices_size <= (size_t)device_id) {
DP("Device ID %" PRId64 " does not have a matching RTL.\n", device_id);
HandleTargetOutcome(false);
return;
}
DeviceTy &Device = Devices[device_id];
if (!Device.IsInit) {
DP("Uninit device: ignore");
HandleTargetOutcome(false);
return;
}
@@ -110,7 +171,9 @@ EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
}
#endif
target_data_end(Device, arg_num, args_base, args, arg_sizes, arg_types);
int rc = target_data_end(Device, arg_num, args_base,
args, arg_sizes, arg_types);
HandleTargetOutcome(rc == OFFLOAD_SUCCESS);
}
EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
@@ -118,7 +181,7 @@ EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
__tgt_target_data_end(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
@@ -126,6 +189,7 @@ EXTERN void __tgt_target_data_end_nowait(int64_t device_id, int32_t arg_num,
EXTERN void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
if (IsOffloadDisabled()) return;
DP("Entering data update with %d mappings\n", arg_num);
// No devices available?
@@ -135,11 +199,14 @@ EXTERN void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %" PRId64 " ready\n", device_id);
HandleTargetOutcome(false);
return;
}
DeviceTy& Device = Devices[device_id];
target_data_update(Device, arg_num, args_base, args, arg_sizes, arg_types);
int rc = target_data_update(Device, arg_num, args_base,
args, arg_sizes, arg_types);
HandleTargetOutcome(rc == OFFLOAD_SUCCESS);
}
EXTERN void __tgt_target_data_update_nowait(
@@ -147,7 +214,7 @@ EXTERN void __tgt_target_data_update_nowait(
int64_t *arg_sizes, int64_t *arg_types, int32_t depNum, void *depList,
int32_t noAliasDepNum, void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
__tgt_target_data_update(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
@@ -155,6 +222,7 @@ EXTERN void __tgt_target_data_update_nowait(
EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
if (IsOffloadDisabled()) return OFFLOAD_FAIL;
DP("Entering target region with entry point " DPxMOD " and device Id %"
PRId64 "\n", DPxPTR(host_ptr), device_id);
@@ -164,6 +232,7 @@ EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %" PRId64 " ready\n", device_id);
HandleTargetOutcome(false);
return OFFLOAD_FAIL;
}
@@ -177,7 +246,7 @@ EXTERN int __tgt_target(int64_t device_id, void *host_ptr, int32_t arg_num,
int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
arg_types, 0, 0, false /*team*/);
HandleTargetOutcome(rc == OFFLOAD_SUCCESS);
return rc;
}
@@ -186,7 +255,7 @@ EXTERN int __tgt_target_nowait(int64_t device_id, void *host_ptr,
int64_t *arg_types, int32_t depNum, void *depList, int32_t noAliasDepNum,
void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
return __tgt_target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
arg_types);
@@ -195,6 +264,7 @@ EXTERN int __tgt_target_nowait(int64_t device_id, void *host_ptr,
EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr,
int32_t arg_num, void **args_base, void **args, int64_t *arg_sizes,
int64_t *arg_types, int32_t team_num, int32_t thread_limit) {
if (IsOffloadDisabled()) return OFFLOAD_FAIL;
DP("Entering target region with entry point " DPxMOD " and device Id %"
PRId64 "\n", DPxPTR(host_ptr), device_id);
@@ -204,6 +274,7 @@ EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr,
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %" PRId64 " ready\n", device_id);
HandleTargetOutcome(false);
return OFFLOAD_FAIL;
}
@@ -217,6 +288,7 @@ EXTERN int __tgt_target_teams(int64_t device_id, void *host_ptr,
int rc = target(device_id, host_ptr, arg_num, args_base, args, arg_sizes,
arg_types, team_num, thread_limit, true /*team*/);
HandleTargetOutcome(rc == OFFLOAD_SUCCESS);
return rc;
}
@@ -226,26 +298,53 @@ EXTERN int __tgt_target_teams_nowait(int64_t device_id, void *host_ptr,
int64_t *arg_types, int32_t team_num, int32_t thread_limit, int32_t depNum,
void *depList, int32_t noAliasDepNum, void *noAliasDepList) {
if (depNum + noAliasDepNum > 0)
__kmpc_omp_taskwait(NULL, 0);
__kmpc_omp_taskwait(NULL, __kmpc_global_thread_num(NULL));
return __tgt_target_teams(device_id, host_ptr, arg_num, args_base, args,
arg_sizes, arg_types, team_num, thread_limit);
}
// Get the current number of components for a user-defined mapper.
EXTERN int64_t __tgt_mapper_num_components(void *rt_mapper_handle) {
auto *MapperComponentsPtr = (struct MapperComponentsTy *)rt_mapper_handle;
int64_t size = MapperComponentsPtr->Components.size();
DP("__tgt_mapper_num_components(Handle=" DPxMOD ") returns %" PRId64 "\n",
DPxPTR(rt_mapper_handle), size);
return size;
}
// Push back one component for a user-defined mapper.
EXTERN void __tgt_push_mapper_component(void *rt_mapper_handle, void *base,
void *begin, int64_t size,
int64_t type) {
DP("__tgt_push_mapper_component(Handle=" DPxMOD
") adds an entry (Base=" DPxMOD ", Begin=" DPxMOD ", Size=%" PRId64
", Type=0x%" PRIx64 ").\n",
DPxPTR(rt_mapper_handle), DPxPTR(base), DPxPTR(begin), size, type);
auto *MapperComponentsPtr = (struct MapperComponentsTy *)rt_mapper_handle;
MapperComponentsPtr->Components.push_back(
MapComponentInfoTy(base, begin, size, type));
}
// The trip count mechanism will be revised - this scheme is not thread-safe.
EXTERN void __kmpc_push_target_tripcount(int64_t device_id,
uint64_t loop_tripcount) {
if (IsOffloadDisabled())
return;
if (device_id == OFFLOAD_DEVICE_DEFAULT) {
device_id = omp_get_default_device();
}
if (CheckDeviceAndCtors(device_id) != OFFLOAD_SUCCESS) {
DP("Failed to get device %" PRId64 " ready\n", device_id);
HandleTargetOutcome(false);
return;
}
DP("__kmpc_push_target_tripcount(%" PRId64 ", %" PRIu64 ")\n", device_id,
loop_tripcount);
Devices[device_id].loopTripCnt = loop_tripcount;
TblMapMtx.lock();
Devices[device_id].LoopTripCnt.emplace(__kmpc_global_thread_num(NULL),
loop_tripcount);
TblMapMtx.unlock();
}
+187 -94
View File
@@ -1,9 +1,8 @@
//===------ omptarget.cpp - Target independent OpenMP target RTL -- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -25,6 +24,8 @@
int DebugLevel = 0;
#endif // OMPTARGET_DEBUG
/* All begin addresses for partially mapped structs must be 8-aligned in order
* to ensure proper alignment of members. E.g.
*
@@ -212,7 +213,6 @@ static int32_t member_of(int64_t type) {
int target_data_begin(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
// process each input.
int rc = OFFLOAD_SUCCESS;
for (int32_t i = 0; i < arg_num; ++i) {
// Ignore private variables and arrays - there is no mapping for them.
if ((arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) ||
@@ -242,7 +242,11 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
// Address of pointer on the host and device, respectively.
void *Pointer_HstPtrBegin, *Pointer_TgtPtrBegin;
bool IsNew, Pointer_IsNew;
bool IsHostPtr = false;
bool IsImplicit = arg_types[i] & OMP_TGT_MAPTYPE_IMPLICIT;
// Force the creation of a device side copy of the data when:
// a close map modifier was associated with a map that contained a to.
bool HasCloseModifier = arg_types[i] & OMP_TGT_MAPTYPE_CLOSE;
// UpdateRef is based on MEMBER_OF instead of TARGET_PARAM because if we
// have reached this point via __tgt_target_data_begin and not __tgt_target
// then no argument is marked as TARGET_PARAM ("omp target data map" is not
@@ -253,10 +257,12 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
DP("Has a pointer entry: \n");
// base is address of pointer.
Pointer_TgtPtrBegin = Device.getOrAllocTgtPtr(HstPtrBase, HstPtrBase,
sizeof(void *), Pointer_IsNew, IsImplicit, UpdateRef);
sizeof(void *), Pointer_IsNew, IsHostPtr, IsImplicit, UpdateRef,
HasCloseModifier);
if (!Pointer_TgtPtrBegin) {
DP("Call to getOrAllocTgtPtr returned null pointer (device failure or "
"illegal mapping).\n");
return OFFLOAD_FAIL;
}
DP("There are %zu bytes allocated at target address " DPxMOD " - is%s new"
"\n", sizeof(void *), DPxPTR(Pointer_TgtPtrBegin),
@@ -268,7 +274,7 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
}
void *TgtPtrBegin = Device.getOrAllocTgtPtr(HstPtrBegin, HstPtrBase,
data_size, IsNew, IsImplicit, UpdateRef);
data_size, IsNew, IsHostPtr, IsImplicit, UpdateRef, HasCloseModifier);
if (!TgtPtrBegin && data_size) {
// If data_size==0, then the argument could be a zero-length pointer to
// NULL, so getOrAlloc() returning NULL is not an error.
@@ -288,30 +294,33 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
bool copy = false;
if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS)) {
copy = true;
} else if (arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) {
// Copy data only if the "parent" struct has RefCount==1.
int32_t parent_idx = member_of(arg_types[i]);
long parent_rc = Device.getMapEntryRefCnt(args[parent_idx]);
assert(parent_rc > 0 && "parent struct not found");
if (parent_rc == 1) {
if (!(RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
HasCloseModifier) {
if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS)) {
copy = true;
} else if (arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) {
// Copy data only if the "parent" struct has RefCount==1.
int32_t parent_idx = member_of(arg_types[i]);
long parent_rc = Device.getMapEntryRefCnt(args[parent_idx]);
assert(parent_rc > 0 && "parent struct not found");
if (parent_rc == 1) {
copy = true;
}
}
}
if (copy) {
if (copy && !IsHostPtr) {
DP("Moving %" PRId64 " bytes (hst:" DPxMOD ") -> (tgt:" DPxMOD ")\n",
data_size, DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBegin));
int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, data_size);
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
rc = OFFLOAD_FAIL;
return OFFLOAD_FAIL;
}
}
}
if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ) {
if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ && !IsHostPtr) {
DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n",
DPxPTR(Pointer_TgtPtrBegin), DPxPTR(TgtPtrBegin));
uint64_t Delta = (uint64_t)HstPtrBegin - (uint64_t)HstPtrBase;
@@ -320,7 +329,7 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
sizeof(void *));
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
rc = OFFLOAD_FAIL;
return OFFLOAD_FAIL;
}
// create shadow pointers for this entry
Device.ShadowMtx.lock();
@@ -330,13 +339,12 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
}
}
return rc;
return OFFLOAD_SUCCESS;
}
/// Internal function to undo the mapping and retrieve the data from the device.
int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types) {
int rc = OFFLOAD_SUCCESS;
// process each input.
for (int32_t i = arg_num - 1; i >= 0; --i) {
// Ignore private variables and arrays - there is no mapping for them.
@@ -363,14 +371,15 @@ int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
}
}
bool IsLast;
bool IsLast, IsHostPtr;
bool UpdateRef = !(arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) ||
(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ);
bool ForceDelete = arg_types[i] & OMP_TGT_MAPTYPE_DELETE;
bool HasCloseModifier = arg_types[i] & OMP_TGT_MAPTYPE_CLOSE;
// If PTR_AND_OBJ, HstPtrBegin is address of pointee
void *TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, data_size, IsLast,
UpdateRef);
UpdateRef, IsHostPtr);
DP("There are %" PRId64 " bytes allocated at target address " DPxMOD
" - is%s last\n", data_size, DPxPTR(TgtPtrBegin),
(IsLast ? "" : " not"));
@@ -387,24 +396,29 @@ int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
bool Always = arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS;
bool CopyMember = false;
if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
!(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) {
// Copy data only if the "parent" struct has RefCount==1.
int32_t parent_idx = member_of(arg_types[i]);
long parent_rc = Device.getMapEntryRefCnt(args[parent_idx]);
assert(parent_rc > 0 && "parent struct not found");
if (parent_rc == 1) {
CopyMember = true;
if (!(RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
HasCloseModifier) {
if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
!(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) {
// Copy data only if the "parent" struct has RefCount==1.
int32_t parent_idx = member_of(arg_types[i]);
long parent_rc = Device.getMapEntryRefCnt(args[parent_idx]);
assert(parent_rc > 0 && "parent struct not found");
if (parent_rc == 1) {
CopyMember = true;
}
}
}
if (DelEntry || Always || CopyMember) {
if ((DelEntry || Always || CopyMember) &&
!(RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
TgtPtrBegin == HstPtrBegin)) {
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
data_size, DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
int rt = Device.data_retrieve(HstPtrBegin, TgtPtrBegin, data_size);
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data from device failed.\n");
rc = OFFLOAD_FAIL;
return OFFLOAD_FAIL;
}
}
}
@@ -417,13 +431,15 @@ int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
uintptr_t ub = (uintptr_t) HstPtrBegin + data_size;
Device.ShadowMtx.lock();
for (ShadowPtrListTy::iterator it = Device.ShadowPtrMap.begin();
it != Device.ShadowPtrMap.end(); ++it) {
it != Device.ShadowPtrMap.end();) {
void **ShadowHstPtrAddr = (void**) it->first;
// An STL map is sorted on its keys; use this property
// to quickly determine when to break out of the loop.
if ((uintptr_t) ShadowHstPtrAddr < lb)
if ((uintptr_t) ShadowHstPtrAddr < lb) {
++it;
continue;
}
if ((uintptr_t) ShadowHstPtrAddr >= ub)
break;
@@ -437,27 +453,30 @@ int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
// If the struct is to be deallocated, remove the shadow entry.
if (DelEntry) {
DP("Removing shadow pointer " DPxMOD "\n", DPxPTR(ShadowHstPtrAddr));
Device.ShadowPtrMap.erase(it);
it = Device.ShadowPtrMap.erase(it);
} else {
++it;
}
}
Device.ShadowMtx.unlock();
// Deallocate map
if (DelEntry) {
int rt = Device.deallocTgtPtr(HstPtrBegin, data_size, ForceDelete);
int rt = Device.deallocTgtPtr(HstPtrBegin, data_size, ForceDelete,
HasCloseModifier);
if (rt != OFFLOAD_SUCCESS) {
DP("Deallocating data from device failed.\n");
rc = OFFLOAD_FAIL;
return OFFLOAD_FAIL;
}
}
}
}
return rc;
return OFFLOAD_SUCCESS;
}
/// Internal function to pass data to/from the target.
void target_data_update(DeviceTy &Device, int32_t arg_num,
int target_data_update(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types) {
// process each input.
for (int32_t i = 0; i < arg_num; ++i) {
@@ -467,14 +486,29 @@ void target_data_update(DeviceTy &Device, int32_t arg_num,
void *HstPtrBegin = args[i];
int64_t MapSize = arg_sizes[i];
bool IsLast;
bool IsLast, IsHostPtr;
void *TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, MapSize, IsLast,
false);
false, IsHostPtr);
if (!TgtPtrBegin) {
DP("hst data:" DPxMOD " not found, becomes a noop\n", DPxPTR(HstPtrBegin));
continue;
}
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
TgtPtrBegin == HstPtrBegin) {
DP("hst data:" DPxMOD " unified and shared, becomes a noop\n",
DPxPTR(HstPtrBegin));
continue;
}
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
arg_sizes[i], DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
Device.data_retrieve(HstPtrBegin, TgtPtrBegin, MapSize);
int rt = Device.data_retrieve(HstPtrBegin, TgtPtrBegin, MapSize);
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data from device failed.\n");
return OFFLOAD_FAIL;
}
uintptr_t lb = (uintptr_t) HstPtrBegin;
uintptr_t ub = (uintptr_t) HstPtrBegin + MapSize;
@@ -497,7 +531,11 @@ void target_data_update(DeviceTy &Device, int32_t arg_num,
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
DP("Moving %" PRId64 " bytes (hst:" DPxMOD ") -> (tgt:" DPxMOD ")\n",
arg_sizes[i], DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBegin));
Device.data_submit(TgtPtrBegin, HstPtrBegin, MapSize);
int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, MapSize);
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
return OFFLOAD_FAIL;
}
uintptr_t lb = (uintptr_t) HstPtrBegin;
uintptr_t ub = (uintptr_t) HstPtrBegin + MapSize;
@@ -512,12 +550,25 @@ void target_data_update(DeviceTy &Device, int32_t arg_num,
DP("Restoring original target pointer value " DPxMOD " for target "
"pointer " DPxMOD "\n", DPxPTR(it->second.TgtPtrVal),
DPxPTR(it->second.TgtPtrAddr));
Device.data_submit(it->second.TgtPtrAddr,
rt = Device.data_submit(it->second.TgtPtrAddr,
&it->second.TgtPtrVal, sizeof(void *));
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
Device.ShadowMtx.unlock();
return OFFLOAD_FAIL;
}
}
Device.ShadowMtx.unlock();
}
}
return OFFLOAD_SUCCESS;
}
static const unsigned LambdaMapping = OMP_TGT_MAPTYPE_PTR_AND_OBJ |
OMP_TGT_MAPTYPE_LITERAL |
OMP_TGT_MAPTYPE_IMPLICIT;
static bool isLambdaMapping(int64_t Mapping) {
return (Mapping & LambdaMapping) == LambdaMapping;
}
/// performs the same actions as data_begin in case arg_num is
@@ -585,12 +636,8 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
// Move data to device.
int rc = target_data_begin(Device, arg_num, args_base, args, arg_sizes,
arg_types);
if (rc != OFFLOAD_SUCCESS) {
DP("Call to target_data_begin failed, skipping target execution.\n");
// Call target_data_end to dealloc whatever target_data_begin allocated
// and return OFFLOAD_FAIL.
target_data_end(Device, arg_num, args_base, args, arg_sizes, arg_types);
DP("Call to target_data_begin failed, abort target.\n");
return OFFLOAD_FAIL;
}
@@ -599,17 +646,59 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
// List of (first-)private arrays allocated for this target region
std::vector<void *> fpArrays;
std::vector<int> tgtArgsPositions(arg_num, -1);
for (int32_t i = 0; i < arg_num; ++i) {
if (!(arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM)) {
// This is not a target parameter, do not push it into tgt_args.
// Check for lambda mapping.
if (isLambdaMapping(arg_types[i])) {
assert((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
"PTR_AND_OBJ must be also MEMBER_OF.");
unsigned idx = member_of(arg_types[i]);
int tgtIdx = tgtArgsPositions[idx];
assert(tgtIdx != -1 && "Base address must be translated already.");
// The parent lambda must be processed already and it must be the last
// in tgt_args and tgt_offsets arrays.
void *HstPtrVal = args[i];
void *HstPtrBegin = args_base[i];
void *HstPtrBase = args[idx];
bool IsLast, IsHostPtr; // unused.
void *TgtPtrBase =
(void *)((intptr_t)tgt_args[tgtIdx] + tgt_offsets[tgtIdx]);
DP("Parent lambda base " DPxMOD "\n", DPxPTR(TgtPtrBase));
uint64_t Delta = (uint64_t)HstPtrBegin - (uint64_t)HstPtrBase;
void *TgtPtrBegin = (void *)((uintptr_t)TgtPtrBase + Delta);
void *Pointer_TgtPtrBegin =
Device.getTgtPtrBegin(HstPtrVal, arg_sizes[i], IsLast, false,
IsHostPtr);
if (!Pointer_TgtPtrBegin) {
DP("No lambda captured variable mapped (" DPxMOD ") - ignored\n",
DPxPTR(HstPtrVal));
continue;
}
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
TgtPtrBegin == HstPtrBegin) {
DP("Unified memory is active, no need to map lambda captured"
"variable (" DPxMOD ")\n", DPxPTR(HstPtrVal));
continue;
}
DP("Update lambda reference (" DPxMOD ") -> [" DPxMOD "]\n",
DPxPTR(Pointer_TgtPtrBegin), DPxPTR(TgtPtrBegin));
int rt = Device.data_submit(TgtPtrBegin, &Pointer_TgtPtrBegin,
sizeof(void *));
if (rt != OFFLOAD_SUCCESS) {
DP("Copying data to device failed.\n");
return OFFLOAD_FAIL;
}
}
continue;
}
void *HstPtrBegin = args[i];
void *HstPtrBase = args_base[i];
void *TgtPtrBegin;
ptrdiff_t TgtBaseOffset;
bool IsLast; // unused.
bool IsLast, IsHostPtr; // unused.
if (arg_types[i] & OMP_TGT_MAPTYPE_LITERAL) {
DP("Forwarding first-private value " DPxMOD " to the target construct\n",
DPxPTR(HstPtrBase));
@@ -620,42 +709,40 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
TgtPtrBegin = Device.RTL->data_alloc(Device.RTLDeviceID,
arg_sizes[i], HstPtrBegin);
if (!TgtPtrBegin) {
DP ("Data allocation for %sprivate array " DPxMOD " failed\n",
DP ("Data allocation for %sprivate array " DPxMOD " failed, "
"abort target.\n",
(arg_types[i] & OMP_TGT_MAPTYPE_TO ? "first-" : ""),
DPxPTR(HstPtrBegin));
rc = OFFLOAD_FAIL;
break;
} else {
fpArrays.push_back(TgtPtrBegin);
TgtBaseOffset = (intptr_t)HstPtrBase - (intptr_t)HstPtrBegin;
return OFFLOAD_FAIL;
}
fpArrays.push_back(TgtPtrBegin);
TgtBaseOffset = (intptr_t)HstPtrBase - (intptr_t)HstPtrBegin;
#ifdef OMPTARGET_DEBUG
void *TgtPtrBase = (void *)((intptr_t)TgtPtrBegin + TgtBaseOffset);
DP("Allocated %" PRId64 " bytes of target memory at " DPxMOD " for "
"%sprivate array " DPxMOD " - pushing target argument " DPxMOD "\n",
arg_sizes[i], DPxPTR(TgtPtrBegin),
(arg_types[i] & OMP_TGT_MAPTYPE_TO ? "first-" : ""),
DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBase));
void *TgtPtrBase = (void *)((intptr_t)TgtPtrBegin + TgtBaseOffset);
DP("Allocated %" PRId64 " bytes of target memory at " DPxMOD " for "
"%sprivate array " DPxMOD " - pushing target argument " DPxMOD "\n",
arg_sizes[i], DPxPTR(TgtPtrBegin),
(arg_types[i] & OMP_TGT_MAPTYPE_TO ? "first-" : ""),
DPxPTR(HstPtrBegin), DPxPTR(TgtPtrBase));
#endif
// If first-private, copy data from host
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, arg_sizes[i]);
if (rt != OFFLOAD_SUCCESS) {
DP ("Copying data to device failed.\n");
rc = OFFLOAD_FAIL;
break;
}
// If first-private, copy data from host
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
int rt = Device.data_submit(TgtPtrBegin, HstPtrBegin, arg_sizes[i]);
if (rt != OFFLOAD_SUCCESS) {
DP ("Copying data to device failed, failed.\n");
return OFFLOAD_FAIL;
}
}
} else if (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ) {
TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBase, sizeof(void *), IsLast,
false);
false, IsHostPtr);
TgtBaseOffset = 0; // no offset for ptrs.
DP("Obtained target argument " DPxMOD " from host pointer " DPxMOD " to "
"object " DPxMOD "\n", DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBase),
DPxPTR(HstPtrBase));
} else {
TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, arg_sizes[i], IsLast,
false);
false, IsHostPtr);
TgtBaseOffset = (intptr_t)HstPtrBase - (intptr_t)HstPtrBegin;
#ifdef OMPTARGET_DEBUG
void *TgtPtrBase = (void *)((intptr_t)TgtPtrBegin + TgtBaseOffset);
@@ -663,6 +750,7 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
DPxPTR(TgtPtrBase), DPxPTR(HstPtrBegin));
#endif
}
tgtArgsPositions[i] = tgt_args.size();
tgt_args.push_back(TgtPtrBegin);
tgt_offsets.push_back(TgtBaseOffset);
}
@@ -671,25 +759,31 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
"Size mismatch in arguments and offsets");
// Pop loop trip count
uint64_t ltc = Device.loopTripCnt;
Device.loopTripCnt = 0;
uint64_t ltc = 0;
TblMapMtx.lock();
auto I = Device.LoopTripCnt.find(__kmpc_global_thread_num(NULL));
if (I != Device.LoopTripCnt.end()) {
ltc = I->second;
Device.LoopTripCnt.erase(I);
DP("loop trip count is %lu.\n", ltc);
}
TblMapMtx.unlock();
// Launch device execution.
if (rc == OFFLOAD_SUCCESS) {
DP("Launching target execution %s with pointer " DPxMOD " (index=%d).\n",
TargetTable->EntriesBegin[TM->Index].name,
DPxPTR(TargetTable->EntriesBegin[TM->Index].addr), TM->Index);
if (IsTeamConstruct) {
rc = Device.run_team_region(TargetTable->EntriesBegin[TM->Index].addr,
&tgt_args[0], &tgt_offsets[0], tgt_args.size(), team_num,
thread_limit, ltc);
} else {
rc = Device.run_region(TargetTable->EntriesBegin[TM->Index].addr,
&tgt_args[0], &tgt_offsets[0], tgt_args.size());
}
DP("Launching target execution %s with pointer " DPxMOD " (index=%d).\n",
TargetTable->EntriesBegin[TM->Index].name,
DPxPTR(TargetTable->EntriesBegin[TM->Index].addr), TM->Index);
if (IsTeamConstruct) {
rc = Device.run_team_region(TargetTable->EntriesBegin[TM->Index].addr,
&tgt_args[0], &tgt_offsets[0], tgt_args.size(), team_num,
thread_limit, ltc);
} else {
DP("Errors occurred while obtaining target arguments, skipping kernel "
"execution\n");
rc = Device.run_region(TargetTable->EntriesBegin[TM->Index].addr,
&tgt_args[0], &tgt_offsets[0], tgt_args.size());
}
if (rc != OFFLOAD_SUCCESS) {
DP ("Executing target region abort target.\n");
return OFFLOAD_FAIL;
}
// Deallocate (first-)private arrays
@@ -697,18 +791,17 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
int rt = Device.RTL->data_delete(Device.RTLDeviceID, it);
if (rt != OFFLOAD_SUCCESS) {
DP("Deallocation of (first-)private arrays failed.\n");
rc = OFFLOAD_FAIL;
return OFFLOAD_FAIL;
}
}
// Move data from device.
int rt = target_data_end(Device, arg_num, args_base, args, arg_sizes,
arg_types);
if (rt != OFFLOAD_SUCCESS) {
DP("Call to target_data_end failed.\n");
rc = OFFLOAD_FAIL;
DP("Call to target_data_end failed, abort targe.\n");
return OFFLOAD_FAIL;
}
return rc;
return OFFLOAD_SUCCESS;
}
+51 -5
View File
@@ -1,9 +1,8 @@
//===---------- private.h - Target independent OpenMP target RTL ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -24,7 +23,7 @@ extern int target_data_begin(DeviceTy &Device, int32_t arg_num,
extern int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
void **args, int64_t *arg_sizes, int64_t *arg_types);
extern void target_data_update(DeviceTy &Device, int32_t arg_num,
extern int target_data_update(DeviceTy &Device, int32_t arg_num,
void **args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
extern int target(int64_t device_id, void *host_ptr, int32_t arg_num,
@@ -33,12 +32,59 @@ extern int target(int64_t device_id, void *host_ptr, int32_t arg_num,
extern int CheckDeviceAndCtors(int64_t device_id);
// enum for OMP_TARGET_OFFLOAD; keep in sync with kmp.h definition
enum kmp_target_offload_kind {
tgt_disabled = 0,
tgt_default = 1,
tgt_mandatory = 2
};
typedef enum kmp_target_offload_kind kmp_target_offload_kind_t;
extern kmp_target_offload_kind_t TargetOffloadPolicy;
// This structure stores information of a mapped memory region.
struct MapComponentInfoTy {
void *Base;
void *Begin;
int64_t Size;
int64_t Type;
MapComponentInfoTy() = default;
MapComponentInfoTy(void *Base, void *Begin, int64_t Size, int64_t Type)
: Base(Base), Begin(Begin), Size(Size), Type(Type) {}
};
// This structure stores all components of a user-defined mapper. The number of
// components are dynamically decided, so we utilize C++ STL vector
// implementation here.
struct MapperComponentsTy {
std::vector<MapComponentInfoTy> Components;
};
////////////////////////////////////////////////////////////////////////////////
// implemtation for fatal messages
////////////////////////////////////////////////////////////////////////////////
#define FATAL_MESSAGE0(_num, _str) \
do { \
fprintf(stderr, "Libomptarget fatal error %d: %s\n", _num, _str); \
exit(1); \
} while (0)
#define FATAL_MESSAGE(_num, _str, ...) \
do { \
fprintf(stderr, "Libomptarget fatal error %d:" _str "\n", _num, \
__VA_ARGS__); \
exit(1); \
} while (0)
// Implemented in libomp, they are called from within __tgt_* functions.
#ifdef __cplusplus
extern "C" {
#endif
// functions that extract info from libomp; keep in sync
int omp_get_default_device(void) __attribute__((weak));
int32_t __kmpc_omp_taskwait(void *loc_ref, int32_t gtid) __attribute__((weak));
int32_t __kmpc_global_thread_num(void *) __attribute__((weak));
int __kmpc_get_target_offload(void) __attribute__((weak));
#ifdef __cplusplus
}
#endif
+49 -11
View File
@@ -1,9 +1,8 @@
//===----------- rtl.cpp - Target independent OpenMP target RTL -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -46,9 +45,8 @@ void RTLsTy::LoadRTLs() {
#endif // OMPTARGET_DEBUG
// Parse environment variable OMP_TARGET_OFFLOAD (if set)
char *envStr = getenv("OMP_TARGET_OFFLOAD");
if (envStr && !strcmp(envStr, "DISABLED")) {
DP("Target offloading disabled by environment\n");
TargetOffloadPolicy = (kmp_target_offload_kind_t) __kmpc_get_target_offload();
if (TargetOffloadPolicy == tgt_disabled) {
return;
}
@@ -109,6 +107,10 @@ void RTLsTy::LoadRTLs() {
dynlib_handle, "__tgt_rtl_run_target_team_region")))
continue;
// Optional functions
*((void**) &R.init_requires) = dlsym(
dynlib_handle, "__tgt_rtl_init_requires");
// No devices are supported by this RTL?
if (!(R.NumberOfDevices = R.number_of_devices())) {
DP("No devices supported in this RTL\n");
@@ -188,6 +190,46 @@ static void RegisterGlobalCtorsDtorsForImage(__tgt_bin_desc *desc,
}
}
void RTLsTy::RegisterRequires(int64_t flags) {
// TODO: add more elaborate check.
// Minimal check: only set requires flags if previous value
// is undefined. This ensures that only the first call to this
// function will set the requires flags. All subsequent calls
// will be checked for compatibility.
assert(flags != OMP_REQ_UNDEFINED &&
"illegal undefined flag for requires directive!");
if (RequiresFlags == OMP_REQ_UNDEFINED) {
RequiresFlags = flags;
return;
}
// If multiple compilation units are present enforce
// consistency across all of them for require clauses:
// - reverse_offload
// - unified_address
// - unified_shared_memory
if ((RequiresFlags & OMP_REQ_REVERSE_OFFLOAD) !=
(flags & OMP_REQ_REVERSE_OFFLOAD)) {
FATAL_MESSAGE0(1,
"'#pragma omp requires reverse_offload' not used consistently!");
}
if ((RequiresFlags & OMP_REQ_UNIFIED_ADDRESS) !=
(flags & OMP_REQ_UNIFIED_ADDRESS)) {
FATAL_MESSAGE0(1,
"'#pragma omp requires unified_address' not used consistently!");
}
if ((RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) !=
(flags & OMP_REQ_UNIFIED_SHARED_MEMORY)) {
FATAL_MESSAGE0(1,
"'#pragma omp requires unified_shared_memory' not used consistently!");
}
// TODO: insert any other missing checks
DP("New requires flags %ld compatible with existing %ld!\n",
flags, RequiresFlags);
}
void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
// Attempt to load all plugins available in the system.
std::call_once(initFlag, &RTLsTy::LoadRTLs, this);
@@ -216,7 +258,6 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
if (!R.isUsed) {
// Initialize the device information for the RTL we are about to use.
DeviceTy device(&R);
size_t start = Devices.size();
Devices.resize(start + R.NumberOfDevices, device);
for (int32_t device_id = 0; device_id < R.NumberOfDevices;
@@ -225,9 +266,6 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
Devices[start + device_id].DeviceID = start + device_id;
// RTL local device ID
Devices[start + device_id].RTLDeviceID = device_id;
// Save pointer to device in RTL in case we want to unregister the RTL
R.Devices.push_back(&Devices[start + device_id]);
}
// Initialize the index of this RTL and save it in the used RTLs.
+14 -9
View File
@@ -1,9 +1,8 @@
//===------------ rtl.h - Target independent OpenMP target RTL ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -37,13 +36,13 @@ struct RTLInfoTy {
int32_t);
typedef int32_t(run_team_region_ty)(int32_t, void *, void **, ptrdiff_t *,
int32_t, int32_t, int32_t, uint64_t);
typedef int64_t(init_requires_ty)(int64_t);
int32_t Idx; // RTL index, index is the number of devices
// of other RTLs that were registered before,
// i.e. the OpenMP index of the first device
// to be registered with this RTL.
int32_t NumberOfDevices; // Number of devices this RTL deals with.
std::vector<DeviceTy *> Devices; // one per device (NumberOfDevices in total).
void *LibraryHandler;
@@ -62,6 +61,7 @@ struct RTLInfoTy {
data_delete_ty *data_delete;
run_region_ty *run_region;
run_team_region_ty *run_team_region;
init_requires_ty *init_requires;
// Are there images associated with this RTL.
bool isUsed;
@@ -74,19 +74,18 @@ struct RTLInfoTy {
// The existence of the mutex above makes RTLInfoTy non-copyable.
// We need to provide a copy constructor explicitly.
RTLInfoTy()
: Idx(-1), NumberOfDevices(-1), Devices(), LibraryHandler(0),
: Idx(-1), NumberOfDevices(-1), LibraryHandler(0),
#ifdef OMPTARGET_DEBUG
RTLName(),
#endif
is_valid_binary(0), number_of_devices(0), init_device(0),
load_binary(0), data_alloc(0), data_submit(0), data_retrieve(0),
data_delete(0), run_region(0), run_team_region(0), isUsed(false),
Mtx() {}
data_delete(0), run_region(0), run_team_region(0),
init_requires(0), isUsed(false), Mtx() {}
RTLInfoTy(const RTLInfoTy &r) : Mtx() {
Idx = r.Idx;
NumberOfDevices = r.NumberOfDevices;
Devices = r.Devices;
LibraryHandler = r.LibraryHandler;
#ifdef OMPTARGET_DEBUG
RTLName = r.RTLName;
@@ -101,6 +100,7 @@ struct RTLInfoTy {
data_delete = r.data_delete;
run_region = r.run_region;
run_team_region = r.run_team_region;
init_requires = r.init_requires;
isUsed = r.isUsed;
}
};
@@ -121,8 +121,13 @@ public:
// binaries.
std::vector<RTLInfoTy *> UsedRTLs;
int64_t RequiresFlags;
explicit RTLsTy() {}
// Register the clauses of the requires directive.
void RegisterRequires(int64_t flags);
// Register a shared library with all (compatible) RTLs.
void RegisterLib(__tgt_bin_desc *desc);
+1 -10
View File
@@ -6,7 +6,7 @@ if(NOT OPENMP_TEST_COMPILER_ID STREQUAL "Clang" OR
return()
endif()
if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
if(LIBOMPTARGET_ENABLE_DEBUG)
set(LIBOMPTARGET_DEBUG True)
else()
set(LIBOMPTARGET_DEBUG False)
@@ -14,15 +14,6 @@ endif()
add_openmp_testsuite(check-libomptarget "Running libomptarget tests" ${CMAKE_CURRENT_BINARY_DIR} DEPENDS omptarget omp)
if(${OPENMP_STANDALONE_BUILD})
set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../../runtime/src" CACHE STRING
"Path to folder containing omp.h")
set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/../../runtime/src" CACHE STRING
"Path to folder containing libomp.so")
else()
set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${LIBOMPTARGET_BINARY_DIR}/../runtime/src")
endif()
# Configure the lit.site.cfg.in file
set(AUTO_GEN_COMMENT "## Autogenerated by libomptarget configuration.\n# Do not edit!")
configure_file(lit.site.cfg.in lit.site.cfg @ONLY)
@@ -0,0 +1,36 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
#include <stdio.h>
#include <omp.h>
int test_omp_get_num_devices()
{
/* checks that omp_get_num_devices() > 0 */
int num_devices = omp_get_num_devices();
printf("num_devices = %d\n", num_devices);
#pragma omp target
{}
return (num_devices > 0);
}
int main()
{
int i;
int failed=0;
if (!test_omp_get_num_devices()) {
failed++;
}
if (failed)
printf("FAIL\n");
else
printf("PASS\n");
return failed;
}
// CHECK: PASS
+5
View File
@@ -41,6 +41,11 @@ if config.omp_host_rtl_directory:
config.test_flags = config.test_flags + " " + config.test_extra_flags
# Allow REQUIRES / UNSUPPORTED / XFAIL to work
config.target_triple = [ ]
for feature in config.test_compiler_features:
config.available_features.add(feature)
if config.libomptarget_debug:
config.available_features.add('libomptarget-debug')
+2 -1
View File
@@ -2,6 +2,7 @@
config.test_c_compiler = "@OPENMP_TEST_C_COMPILER@"
config.test_cxx_compiler = "@OPENMP_TEST_CXX_COMPILER@"
config.test_compiler_features = @OPENMP_TEST_COMPILER_FEATURES@
config.test_openmp_flags = "@OPENMP_TEST_OPENMP_FLAGS@"
config.test_extra_flags = "@OPENMP_TEST_FLAGS@"
config.libomptarget_obj_root = "@CMAKE_CURRENT_BINARY_DIR@"
@@ -15,4 +16,4 @@ config.libomptarget_filecheck = "@OPENMP_FILECHECK_EXECUTABLE@"
config.libomptarget_debug = @LIBOMPTARGET_DEBUG@
# Let the main config do the real work.
lit_config.load_config(config, "@LIBOMPTARGET_BASE_DIR@/test/lit.cfg")
lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
@@ -0,0 +1,47 @@
// RUN: %libomptarget-compilexx-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-x86_64-pc-linux-gnu
#include <cstdio>
#include <cstdlib>
#include <vector>
// Data structure definitions copied from OpenMP RTL.
struct MapComponentInfoTy {
void *Base;
void *Begin;
int64_t Size;
int64_t Type;
MapComponentInfoTy() = default;
MapComponentInfoTy(void *Base, void *Begin, int64_t Size, int64_t Type)
: Base(Base), Begin(Begin), Size(Size), Type(Type) {}
};
struct MapperComponentsTy {
std::vector<MapComponentInfoTy> Components;
};
// OpenMP RTL interfaces
#ifdef __cplusplus
extern "C" {
#endif
int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
void __tgt_push_mapper_component(void *rt_mapper_handle, void *base,
void *begin, int64_t size, int64_t type);
#ifdef __cplusplus
}
#endif
int main(int argc, char *argv[]) {
MapperComponentsTy MC;
void *base, *begin;
int64_t size, type;
// Push 2 elements into MC.
__tgt_push_mapper_component((void *)&MC, base, begin, size, type);
__tgt_push_mapper_component((void *)&MC, base, begin, size, type);
int64_t num = __tgt_mapper_num_components((void *)&MC);
// CHECK: num=2
printf("num=%lld\n", num);
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
// Clang 6.0 doesn't use the new map interface, undefined behavior when
// the compiler emits "old" interface code for structures.
// UNSUPPORTED: clang-6
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *ptr1;
int *ptr2;
} StructWithPtrs;
int main(int argc, char *argv[]) {
StructWithPtrs s, s2;
s.ptr1 = malloc(sizeof(int));
s.ptr2 = malloc(2 * sizeof(int));
s2.ptr1 = malloc(sizeof(int));
s2.ptr2 = malloc(2 * sizeof(int));
#pragma omp target enter data map(to: s2.ptr2[0:1])
#pragma omp target map(s.ptr1[0:1], s.ptr2[0:2])
{
s.ptr1[0] = 1;
s.ptr2[0] = 2;
s.ptr2[1] = 3;
}
#pragma omp target exit data map(from: s2.ptr1[0:1], s2.ptr2[0:1])
// CHECK: s.ptr1[0] = 1
// CHECK: s.ptr2[0] = 2
// CHECK: s.ptr2[1] = 3
printf("s.ptr1[0] = %d\n", s.ptr1[0]);
printf("s.ptr2[0] = %d\n", s.ptr2[0]);
printf("s.ptr2[1] = %d\n", s.ptr2[1]);
free(s.ptr1);
free(s.ptr2);
free(s2.ptr1);
free(s2.ptr2);
return 0;
}
@@ -0,0 +1,36 @@
// RUN: %libomptarget-compile-aarch64-unknown-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-aarch64-unknown-linux-gnu 2>&1 | %fcheck-aarch64-unknown-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-powerpc64-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-powerpc64-ibm-linux-gnu 2>&1 | %fcheck-powerpc64-ibm-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-powerpc64le-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-powerpc64le-ibm-linux-gnu 2>&1 | %fcheck-powerpc64le-ibm-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-x86_64-pc-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-x86_64-pc-linux-gnu 2>&1 | %fcheck-x86_64-pc-linux-gnu -allow-empty -check-prefix=DEBUG
// REQUIRES: libomptarget-debug
/*
Test for looptripcount being popped from runtime stack.
*/
#include <stdio.h>
#include <omp.h>
int main()
{
int N = 128;
int NN = 1024;
int num_teams[NN];
int num_threads[NN];
printf("#pragma omp target teams distribute parallel for thread_limit(4)\n");
#pragma omp target teams distribute parallel for thread_limit(4)
for (int j = 0; j< N; j++) {
num_threads[j] = omp_get_num_threads();
num_teams[j] = omp_get_num_teams();
}
printf("num_threads %d num_teams %d\n", num_threads[0], num_teams[0]);
// DEBUG: loop trip count is 128
printf("#pragma omp target teams distribute parallel for\n");
#pragma omp target teams distribute parallel for
for (int j = 0; j< N; j++) {
num_threads[j] = omp_get_num_threads();
num_teams[j] = omp_get_num_teams();
}
printf("num_threads %d num_teams %d\n", num_threads[0], num_teams[0]);
// DEBUG: loop trip count is 128
return 0;
}
+46
View File
@@ -0,0 +1,46 @@
// RUN: %libomptarget-compile-aarch64-unknown-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-aarch64-unknown-linux-gnu 2>&1 | %fcheck-aarch64-unknown-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-powerpc64-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-powerpc64-ibm-linux-gnu 2>&1 | %fcheck-powerpc64-ibm-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-powerpc64le-ibm-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-powerpc64le-ibm-linux-gnu 2>&1 | %fcheck-powerpc64le-ibm-linux-gnu -allow-empty -check-prefix=DEBUG
// RUN: %libomptarget-compile-x86_64-pc-linux-gnu && env LIBOMPTARGET_DEBUG=1 %libomptarget-run-x86_64-pc-linux-gnu 2>&1 | %fcheck-x86_64-pc-linux-gnu -allow-empty -check-prefix=DEBUG
// REQUIRES: libomptarget-debug
/*
Test for the 'requires' clause check.
When a target region is used, the requires flags are set in the
runtime for the entire compilation unit. If the flags are set again,
(for whatever reason) the set must be consistent with previously
set values.
*/
#include <stdio.h>
#include <omp.h>
// ---------------------------------------------------------------------------
// Various definitions copied from OpenMP RTL
extern void __tgt_register_requires(int64_t);
// End of definitions copied from OpenMP RTL.
// ---------------------------------------------------------------------------
void run_reg_requires() {
// Before the target region is registered, the requires registers the status
// of the requires clauses. Since there are no requires clauses in this file
// the flags state can only be OMP_REQ_NONE i.e. 1.
// This is the 2nd time this function is called so it should print the debug
// info belonging to the check.
__tgt_register_requires(1);
__tgt_register_requires(1);
// DEBUG: New requires flags 1 compatible with existing 1!
}
// ---------------------------------------------------------------------------
int main() {
run_reg_requires();
// This also runs reg requires for the first time.
#pragma omp target
{}
return 0;
}
@@ -0,0 +1,62 @@
// RUN: %libomptarget-compilexx-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compilexx-run-and-check-x86_64-pc-linux-gnu
#include <omp.h>
#include <stdio.h>
#define N 1024
int A[N];
int B[N];
int C[N];
int main() {
for (int i = 0; i < N; i++)
A[i] = B[i] = i;
#pragma omp parallel num_threads(2)
{
if (omp_get_thread_num() == 1) {
// map data A & B and move to
#pragma omp target enter data map(to : A, B) depend(out : A[0]) nowait
// no data move since already mapped
#pragma omp target map(A, B) depend(out : A[0]) nowait
{
for (int i = 0; i < N; i++)
++A[i];
for (int i = 0; i < N; i++)
++B[i];
}
// no data move since already mapped
#pragma omp target teams num_teams(1) map(A, B) depend(out : A[0]) nowait
{
for (int i = 0; i < N; i++)
++A[i];
for (int i = 0; i < N; i++)
++B[i];
}
// A updated via update
#pragma omp target update from(A) depend(out : A[0]) nowait
// B updated via exit, A just released
#pragma omp target exit data map(release \
: A) map(from \
: B) depend(out \
: A[0]) nowait
} // if
} // parallel
int Sum = 0;
for (int i = 0; i < N; i++)
Sum += A[i] + B[i];
// Sum is 2 * N * (2 + N - 1 + 2) / 2
// CHECK: Sum = 1051648.
printf("Sum = %d.\n", Sum);
return Sum != 2 * N * (2 + N - 1 + 2) / 2;
}
@@ -0,0 +1,164 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
#include <stdio.h>
#include <omp.h>
// ---------------------------------------------------------------------------
// Various definitions copied from OpenMP RTL
extern void __tgt_register_requires(int64_t);
// End of definitions copied from OpenMP RTL.
// ---------------------------------------------------------------------------
#pragma omp requires unified_shared_memory
#define N 1024
void init(int A[], int B[], int C[]) {
for (int i = 0; i < N; ++i) {
A[i] = 0;
B[i] = 1;
C[i] = i;
}
}
int main(int argc, char *argv[]) {
const int device = omp_get_default_device();
// Manual registration of requires flags for Clang versions
// that do not support requires.
__tgt_register_requires(8);
// CHECK: Initial device: -10
printf("Initial device: %d\n", omp_get_initial_device());
//
// Target alloc & target memcpy
//
int A[N], B[N], C[N];
// Init
init(A, B, C);
int *pA, *pB, *pC;
// map ptrs
pA = &A[0];
pB = &B[0];
pC = &C[0];
int *d_A = (int *)omp_target_alloc(N * sizeof(int), device);
int *d_B = (int *)omp_target_alloc(N * sizeof(int), device);
int *d_C = (int *)omp_target_alloc(N * sizeof(int), device);
// CHECK: omp_target_alloc succeeded
printf("omp_target_alloc %s\n", d_A && d_B && d_C ? "succeeded" : "failed");
omp_target_memcpy(d_B, pB, N * sizeof(int), 0, 0, device,
omp_get_initial_device());
omp_target_memcpy(d_C, pC, N * sizeof(int), 0, 0, device,
omp_get_initial_device());
#pragma omp target is_device_ptr(d_A, d_B, d_C) device(device)
{
#pragma omp parallel for schedule(static, 1)
for (int i = 0; i < N; i++) {
d_A[i] = d_B[i] + d_C[i] + 1;
}
}
omp_target_memcpy(pA, d_A, N * sizeof(int), 0, 0, omp_get_initial_device(),
device);
// CHECK: Test omp_target_memcpy: Succeeded
int fail = 0;
for (int i = 0; i < N; ++i) {
if (A[i] != i + 2)
fail++;
}
if (fail) {
printf("Test omp_target_memcpy: Failed\n");
} else {
printf("Test omp_target_memcpy: Succeeded\n");
}
//
// target_is_present and target_associate/disassociate_ptr
//
init(A, B, C);
// CHECK: B is not present, associating it...
// CHECK: omp_target_associate_ptr B succeeded
if (!omp_target_is_present(B, device)) {
printf("B is not present, associating it...\n");
int rc = omp_target_associate_ptr(B, d_B, N * sizeof(int), 0, device);
printf("omp_target_associate_ptr B %s\n", !rc ? "succeeded" : "failed");
}
// CHECK: C is not present, associating it...
// CHECK: omp_target_associate_ptr C succeeded
if (!omp_target_is_present(C, device)) {
printf("C is not present, associating it...\n");
int rc = omp_target_associate_ptr(C, d_C, N * sizeof(int), 0, device);
printf("omp_target_associate_ptr C %s\n", !rc ? "succeeded" : "failed");
}
// CHECK: Inside target data: A is not present
// CHECK: Inside target data: B is present
// CHECK: Inside target data: C is present
#pragma omp target data map(from : B, C) device(device)
{
printf("Inside target data: A is%s present\n",
omp_target_is_present(A, device) ? "" : " not");
printf("Inside target data: B is%s present\n",
omp_target_is_present(B, device) ? "" : " not");
printf("Inside target data: C is%s present\n",
omp_target_is_present(C, device) ? "" : " not");
#pragma omp target map(from : A) device(device)
{
#pragma omp parallel for schedule(static, 1)
for (int i = 0; i < N; i++)
A[i] = B[i] + C[i] + 1;
}
}
// CHECK: B is present, disassociating it...
// CHECK: omp_target_disassociate_ptr B succeeded
// CHECK: C is present, disassociating it...
// CHECK: omp_target_disassociate_ptr C succeeded
if (omp_target_is_present(B, device)) {
printf("B is present, disassociating it...\n");
int rc = omp_target_disassociate_ptr(B, device);
printf("omp_target_disassociate_ptr B %s\n", !rc ? "succeeded" : "failed");
}
if (omp_target_is_present(C, device)) {
printf("C is present, disassociating it...\n");
int rc = omp_target_disassociate_ptr(C, device);
printf("omp_target_disassociate_ptr C %s\n", !rc ? "succeeded" : "failed");
}
// CHECK: Test omp_target_associate_ptr: Succeeded
fail = 0;
for (int i = 0; i < N; ++i) {
if (A[i] != i + 2)
fail++;
}
if (fail) {
printf("Test omp_target_associate_ptr: Failed\n");
} else {
printf("Test omp_target_associate_ptr: Succeeded\n");
}
omp_target_free(d_A, device);
omp_target_free(d_B, device);
omp_target_free(d_C, device);
printf("Done!\n");
return 0;
}
@@ -0,0 +1,95 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
// UNSUPPORTED: clang-6, clang-7, clang-8, clang-9
#include <omp.h>
#include <stdio.h>
#pragma omp requires unified_shared_memory
#define N 1024
int main(int argc, char *argv[]) {
int fails;
void *host_alloc = 0, *device_alloc = 0;
int *a = (int *)malloc(N * sizeof(int));
// Init
for (int i = 0; i < N; ++i) {
a[i] = 10;
}
host_alloc = &a[0];
//
// map + target no close
//
#pragma omp target data map(tofrom : a[ : N]) map(tofrom : device_alloc)
{
#pragma omp target map(tofrom : device_alloc)
{ device_alloc = &a[0]; }
}
// CHECK: a used from unified memory.
if (device_alloc == host_alloc)
printf("a used from unified memory.\n");
//
// map + target with close
//
device_alloc = 0;
#pragma omp target data map(close, tofrom : a[ : N]) map(tofrom : device_alloc)
{
#pragma omp target map(tofrom : device_alloc)
{ device_alloc = &a[0]; }
}
// CHECK: a copied to device.
if (device_alloc != host_alloc)
printf("a copied to device.\n");
//
// map + use_device_ptr no close
//
device_alloc = 0;
#pragma omp target data map(tofrom : a[ : N]) use_device_ptr(a)
{ device_alloc = &a[0]; }
// CHECK: a used from unified memory with use_device_ptr.
if (device_alloc == host_alloc)
printf("a used from unified memory with use_device_ptr.\n");
//
// map + use_device_ptr close
//
device_alloc = 0;
#pragma omp target data map(close, tofrom : a[ : N]) use_device_ptr(a)
{ device_alloc = &a[0]; }
// CHECK: a used from device memory with use_device_ptr.
if (device_alloc != host_alloc)
printf("a used from device memory with use_device_ptr.\n");
//
// map enter/exit + close
//
device_alloc = 0;
#pragma omp target enter data map(close, to : a[ : N])
#pragma omp target map(from : device_alloc)
{ device_alloc = &a[0]; }
#pragma omp target exit data map(from : a[ : N])
// CHECK: a has been mapped to the device.
if (device_alloc != host_alloc)
printf("a has been mapped to the device.\n");
free(a);
// CHECK: Done!
printf("Done!\n");
return 0;
}
@@ -0,0 +1,86 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
#include <omp.h>
#include <stdio.h>
// ---------------------------------------------------------------------------
// Various definitions copied from OpenMP RTL
extern void __tgt_register_requires(int64_t);
extern void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types);
extern void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
void **args_base, void **args,
int64_t *arg_sizes, int64_t *arg_types);
// End of definitions copied from OpenMP RTL.
// ---------------------------------------------------------------------------
#pragma omp requires unified_shared_memory
#define N 1024
int main(int argc, char *argv[]) {
int fails;
void *host_alloc = 0, *device_alloc = 0;
int *a = (int *)malloc(N * sizeof(int));
// Manual registration of requires flags for Clang versions
// that do not support requires.
__tgt_register_requires(8);
// Init
for (int i = 0; i < N; ++i) {
a[i] = 10;
}
host_alloc = &a[0];
// Dummy target region that ensures the runtime library is loaded when
// the target data begin/end functions are manually called below.
#pragma omp target
{}
// Manual calls
int device_id = omp_get_default_device();
int arg_num = 1;
void **args_base = (void **)&a;
void **args = (void **)&a;
int64_t arg_sizes[arg_num];
arg_sizes[0] = sizeof(int) * N;
int64_t arg_types[arg_num];
// Ox400 enables the CLOSE map type in the runtime:
// OMP_TGT_MAPTYPE_CLOSE = 0x400
// OMP_TGT_MAPTYPE_TO = 0x001
arg_types[0] = 0x400 | 0x001;
device_alloc = host_alloc;
__tgt_target_data_begin(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
#pragma omp target data use_device_ptr(a)
{ device_alloc = a; }
__tgt_target_data_end(device_id, arg_num, args_base, args, arg_sizes,
arg_types);
// CHECK: a was copied to the device
if (device_alloc != host_alloc)
printf("a was copied to the device\n");
free(a);
// CHECK: Done!
printf("Done!\n");
return 0;
}
@@ -0,0 +1,135 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
// UNSUPPORTED: clang-6, clang-7, clang-8, clang-9
#include <omp.h>
#include <stdio.h>
#pragma omp requires unified_shared_memory
#define N 1024
int main(int argc, char *argv[]) {
int fails;
void *host_alloc, *device_alloc;
void *host_data, *device_data;
int *alloc = (int *)malloc(N * sizeof(int));
int data[N];
for (int i = 0; i < N; ++i) {
alloc[i] = 10;
data[i] = 1;
}
host_data = &data[0];
host_alloc = &alloc[0];
//
// Test that updates on the device are not visible to host
// when only a TO mapping is used.
//
#pragma omp target map(tofrom \
: device_data, device_alloc) map(close, to \
: alloc[:N], data \
[:N])
{
device_data = &data[0];
device_alloc = &alloc[0];
for (int i = 0; i < N; i++) {
alloc[i] += 1;
data[i] += 1;
}
}
// CHECK: Address of alloc on device different from host address.
if (device_alloc != host_alloc)
printf("Address of alloc on device different from host address.\n");
// CHECK: Address of data on device different from host address.
if (device_data != host_data)
printf("Address of data on device different from host address.\n");
// On the host, check that the arrays have been updated.
// CHECK: Alloc host values not updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (alloc[i] != 10)
fails++;
}
printf("Alloc host values not updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
// CHECK: Data host values not updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (data[i] != 1)
fails++;
}
printf("Data host values not updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
//
// Test that updates on the device are visible on host
// when a from is used.
//
for (int i = 0; i < N; i++) {
alloc[i] += 1;
data[i] += 1;
}
#pragma omp target map(close, tofrom : alloc[:N], data[:N])
{
// CHECK: Alloc device values are correct: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (alloc[i] != 11)
fails++;
}
printf("Alloc device values are correct: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
// CHECK: Data device values are correct: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (data[i] != 2)
fails++;
}
printf("Data device values are correct: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
// Update values on the device
for (int i = 0; i < N; i++) {
alloc[i] += 1;
data[i] += 1;
}
}
// CHECK: Alloc host values updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (alloc[i] != 12)
fails++;
}
printf("Alloc host values updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
// CHECK: Data host values updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (data[i] != 3)
fails++;
}
printf("Data host values updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
free(alloc);
// CHECK: Done!
printf("Done!\n");
return 0;
}
@@ -0,0 +1,114 @@
// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu
// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu
#include <stdio.h>
#include <omp.h>
// ---------------------------------------------------------------------------
// Various definitions copied from OpenMP RTL
extern void __tgt_register_requires(int64_t);
// End of definitions copied from OpenMP RTL.
// ---------------------------------------------------------------------------
#pragma omp requires unified_shared_memory
#define N 1024
int main(int argc, char *argv[]) {
int fails;
void *host_alloc, *device_alloc;
void *host_data, *device_data;
int *alloc = (int *)malloc(N * sizeof(int));
int data[N];
// Manual registration of requires flags for Clang versions
// that do not support requires.
__tgt_register_requires(8);
for (int i = 0; i < N; ++i) {
alloc[i] = 10;
data[i] = 1;
}
host_data = &data[0];
host_alloc = &alloc[0];
// implicit mapping of data
#pragma omp target map(tofrom : device_data, device_alloc)
{
device_data = &data[0];
device_alloc = &alloc[0];
for (int i = 0; i < N; i++) {
alloc[i] += 1;
data[i] += 1;
}
}
// CHECK: Address of alloc on device matches host address.
if (device_alloc == host_alloc)
printf("Address of alloc on device matches host address.\n");
// CHECK: Address of data on device matches host address.
if (device_data == host_data)
printf("Address of data on device matches host address.\n");
// On the host, check that the arrays have been updated.
// CHECK: Alloc device values updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (alloc[i] != 11)
fails++;
}
printf("Alloc device values updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
// CHECK: Data device values updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (data[i] != 2)
fails++;
}
printf("Data device values updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
//
// Test that updates on the host snd on the device are both visible.
//
// Update on the host.
for (int i = 0; i < N; ++i) {
alloc[i] += 1;
data[i] += 1;
}
#pragma omp target
{
// CHECK: Alloc host values updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (alloc[i] != 12)
fails++;
}
printf("Alloc host values updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
// CHECK: Data host values updated: Succeeded
fails = 0;
for (int i = 0; i < N; i++) {
if (data[i] != 3)
fails++;
}
printf("Data host values updated: %s\n",
(fails == 0) ? "Succeeded" : "Failed");
}
free(alloc);
printf("Done!\n");
return 0;
}
+13 -28
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -31,7 +30,7 @@ if(${OPENMP_STANDALONE_BUILD})
# If adding a new architecture, take a look at cmake/LibompGetArchitecture.cmake
libomp_get_architecture(LIBOMP_DETECTED_ARCH)
set(LIBOMP_ARCH ${LIBOMP_DETECTED_ARCH} CACHE STRING
"The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64).")
"The architecture to build for (x86_64/i386/arm/ppc64/ppc64le/aarch64/mic/mips/mips64/riscv64).")
# Should assertions be enabled? They are on by default.
set(LIBOMP_ENABLE_ASSERTIONS TRUE CACHE BOOL
"enable assertions?")
@@ -59,32 +58,21 @@ else() # Part of LLVM build
set(LIBOMP_ARCH aarch64)
elseif(LIBOMP_NATIVE_ARCH MATCHES "arm")
set(LIBOMP_ARCH arm)
elseif(LIBOMP_NATIVE_ARCH MATCHES "riscv64")
set(LIBOMP_ARCH riscv64)
else()
# last ditch effort
libomp_get_architecture(LIBOMP_ARCH)
endif ()
set(LIBOMP_ENABLE_ASSERTIONS ${LLVM_ENABLE_ASSERTIONS})
endif()
libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 mic mips mips64)
libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc64 ppc64le aarch64 mic mips mips64 riscv64)
set(LIBOMP_LIB_TYPE normal CACHE STRING
"Performance,Profiling,Stubs library (normal/profile/stubs)")
libomp_check_variable(LIBOMP_LIB_TYPE normal profile stubs)
set(LIBOMP_OMP_VERSION 50 CACHE STRING
"The OpenMP version (50/45/40/30)")
libomp_check_variable(LIBOMP_OMP_VERSION 50 45 40 30)
# Set the OpenMP Year and Month assiociated with version
if(${LIBOMP_OMP_VERSION} GREATER 50 OR ${LIBOMP_OMP_VERSION} EQUAL 50)
set(LIBOMP_OMP_YEAR_MONTH 201611)
elseif(${LIBOMP_OMP_VERSION} GREATER 45 OR ${LIBOMP_OMP_VERSION} EQUAL 45)
set(LIBOMP_OMP_YEAR_MONTH 201511)
elseif(${LIBOMP_OMP_VERSION} GREATER 40 OR ${LIBOMP_OMP_VERSION} EQUAL 40)
set(LIBOMP_OMP_YEAR_MONTH 201307)
elseif(${LIBOMP_OMP_VERSION} GREATER 30 OR ${LIBOMP_OMP_VERSION} EQUAL 30)
set(LIBOMP_OMP_YEAR_MONTH 201107)
else()
set(LIBOMP_OMP_YEAR_MONTH 200505)
endif()
set(LIBOMP_OMP_YEAR_MONTH 201611)
set(LIBOMP_MIC_ARCH knc CACHE STRING
"Intel(R) Many Integrated Core Architecture (Intel(R) MIC Architecture) (knf/knc). Ignored if not Intel(R) MIC Architecture build.")
if("${LIBOMP_ARCH}" STREQUAL "mic")
@@ -109,8 +97,6 @@ if(NOT DEFINED CMAKE_MACOSX_RPATH)
endif()
# User specified flags. These are appended to the configured flags.
set(LIBOMP_CFLAGS "" CACHE STRING
"Appended user specified C compiler flags.")
set(LIBOMP_CXXFLAGS "" CACHE STRING
"Appended user specified C++ compiler flags.")
set(LIBOMP_CPPFLAGS "" CACHE STRING
@@ -156,6 +142,7 @@ set(PPC64 FALSE)
set(MIC FALSE)
set(MIPS64 FALSE)
set(MIPS FALSE)
set(RISCV64 FALSE)
if("${LIBOMP_ARCH}" STREQUAL "i386" OR "${LIBOMP_ARCH}" STREQUAL "32") # IA-32 architecture
set(IA32 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "x86_64" OR "${LIBOMP_ARCH}" STREQUAL "32e") # Intel(R) 64 architecture
@@ -176,6 +163,8 @@ elseif("${LIBOMP_ARCH}" STREQUAL "mips") # MIPS architecture
set(MIPS TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "mips64") # MIPS64 architecture
set(MIPS64 TRUE)
elseif("${LIBOMP_ARCH}" STREQUAL "riscv64") # RISCV64 architecture
set(RISCV64 TRUE)
endif()
# Set some flags based on build_type
@@ -214,7 +203,7 @@ endif()
set(LIBOMP_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBOMP_SRC_DIR ${LIBOMP_BASE_DIR}/src)
set(LIBOMP_TOOLS_DIR ${LIBOMP_BASE_DIR}/tools)
set(LIBOMP_INC_DIR ${LIBOMP_SRC_DIR}/include/${LIBOMP_OMP_VERSION})
set(LIBOMP_INC_DIR ${LIBOMP_SRC_DIR}/include)
set(LIBOMP_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# Enabling Fortran if it is needed
@@ -302,7 +291,7 @@ endif()
# OMPT-support defaults to ON for OpenMP 5.0+ and if the requirements in
# cmake/config-ix.cmake are fulfilled.
set(OMPT_DEFAULT FALSE)
if ((${LIBOMP_OMP_VERSION} GREATER 49) AND (LIBOMP_HAVE_OMPT_SUPPORT) AND (NOT WIN32))
if ((LIBOMP_HAVE_OMPT_SUPPORT) AND (NOT WIN32))
set(OMPT_DEFAULT TRUE)
endif()
set(LIBOMP_OMPT_SUPPORT ${OMPT_DEFAULT} CACHE BOOL
@@ -315,9 +304,6 @@ set(LIBOMP_OMPT_OPTIONAL TRUE CACHE BOOL
if(LIBOMP_OMPT_SUPPORT AND (NOT LIBOMP_HAVE_OMPT_SUPPORT))
libomp_error_say("OpenMP Tools Interface requested but not available in this implementation")
endif()
if(LIBOMP_OMPT_SUPPORT AND (${LIBOMP_OMP_VERSION} LESS 50))
libomp_error_say("OpenMP Tools Interface only available with OpenMP 5.0, LIBOMP_OMP_VERSION is ${LIBOMP_OMP_VERSION}")
endif()
# TSAN-support
set(LIBOMP_TSAN_SUPPORT FALSE CACHE BOOL
@@ -369,7 +355,6 @@ if(${OPENMP_STANDALONE_BUILD})
libomp_say("Intel(R) MIC Architecture -- ${LIBOMP_MIC_ARCH}")
endif()
libomp_say("Build Type -- ${CMAKE_BUILD_TYPE}")
libomp_say("OpenMP Version -- ${LIBOMP_OMP_VERSION}")
libomp_say("Library Kind -- ${LIBOMP_LIBRARY_KIND}")
libomp_say("Library Type -- ${LIBOMP_LIB_TYPE}")
libomp_say("Fortran Modules -- ${LIBOMP_FORTRAN_MODULES}")
+1
View File
@@ -53,6 +53,7 @@ Architectures Supported
* IBM(R) Power architecture (big endian)
* IBM(R) Power architecture (little endian)
* MIPS and MIPS64 architecture
* RISCV64 architecture
Supported RTL Build Configurations
==================================
+3 -4
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
+3 -4
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
+3 -5
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -29,4 +28,3 @@ function(libomp_get_definitions_flags cppflags)
# CMake doesn't include CPPFLAGS from environment, but we will.
set(${cppflags} ${cppflags_local} ${LIBOMP_CPPFLAGS} $ENV{CPPFLAGS} PARENT_SCOPE)
endfunction()
+7 -12
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -14,16 +13,13 @@
# Create the suffix for the export directory
# - Only add to suffix when not a default value
# - Example suffix: .deb.30.s1
# final export directory: exports/lin_32e.deb.30.s1/lib
# - These suffixes imply the build is a Debug, OpenMP 3.0, Stats-Gathering version of the library
# - Example suffix: .deb.s1
# final export directory: exports/lin_32e.deb.s1/lib
# - These suffixes imply the build is a Debug, Stats-Gathering version of the library
set(libomp_suffix)
libomp_append(libomp_suffix .deb DEBUG_BUILD)
libomp_append(libomp_suffix .dia RELWITHDEBINFO_BUILD)
libomp_append(libomp_suffix .min MINSIZEREL_BUILD)
if(NOT "${LIBOMP_OMP_VERSION}" STREQUAL "45")
libomp_append(libomp_suffix .${LIBOMP_OMP_VERSION})
endif()
libomp_append(libomp_suffix .s1 LIBOMP_STATS)
libomp_append(libomp_suffix .ompt LIBOMP_OMPT_SUPPORT)
if(${LIBOMP_OMPT_SUPPORT})
@@ -57,7 +53,7 @@ add_custom_command(TARGET omp POST_BUILD
)
if(${LIBOMP_OMPT_SUPPORT})
add_custom_command(TARGET omp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ompt.h ${LIBOMP_EXPORTS_CMN_DIR}
COMMAND ${CMAKE_COMMAND} -E copy omp-tools.h ${LIBOMP_EXPORTS_CMN_DIR}
)
endif()
if(${LIBOMP_FORTRAN_MODULES})
@@ -96,4 +92,3 @@ if(WIN32)
COMMAND ${CMAKE_COMMAND} -E copy ${LIBOMPIMP_OUTPUT_DIRECTORY}/${LIBOMP_IMP_LIB_FILE} ${LIBOMP_EXPORTS_LIB_DIR}
)
endif()
+5 -4
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -46,6 +45,8 @@ function(libomp_get_architecture return_arch)
#error ARCHITECTURE=mips64
#elif defined(__mips__) && !defined(__mips64)
#error ARCHITECTURE=mips
#elif defined(__riscv) && __riscv_xlen == 64
#error ARCHITECTURE=riscv64
#else
#error ARCHITECTURE=UnknownArchitecture
#endif
+20 -55
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -23,31 +22,24 @@ macro(libomp_setup_flags flags)
endif()
endmacro()
# Gets flags common to both the C and C++ compiler
function(libomp_get_c_and_cxxflags_common flags)
# C++ compiler flags
function(libomp_get_cxxflags cxxflags)
set(flags_local)
libomp_append(flags_local -fno-exceptions LIBOMP_HAVE_FNO_EXCEPTIONS_FLAG)
libomp_append(flags_local -fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG)
libomp_append(flags_local -Wno-sign-compare LIBOMP_HAVE_WNO_SIGN_COMPARE_FLAG)
libomp_append(flags_local -Wno-unused-function LIBOMP_HAVE_WNO_UNUSED_FUNCTION_FLAG)
libomp_append(flags_local -Wno-unused-local-typedef LIBOMP_HAVE_WNO_UNUSED_LOCAL_TYPEDEF_FLAG)
libomp_append(flags_local -Wno-unused-value LIBOMP_HAVE_WNO_UNUSED_VALUE_FLAG)
libomp_append(flags_local -Wno-unused-variable LIBOMP_HAVE_WNO_UNUSED_VARIABLE_FLAG)
libomp_append(flags_local -Wno-switch LIBOMP_HAVE_WNO_SWITCH_FLAG)
libomp_append(flags_local -Wno-class-memaccess LIBOMP_HAVE_WNO_CLASS_MEMACCESS_FLAG)
libomp_append(flags_local -Wno-covered-switch-default LIBOMP_HAVE_WNO_COVERED_SWITCH_DEFAULT_FLAG)
libomp_append(flags_local -Wno-deprecated-register LIBOMP_HAVE_WNO_DEPRECATED_REGISTER_FLAG)
libomp_append(flags_local -Wno-gnu-anonymous-struct LIBOMP_HAVE_WNO_GNU_ANONYMOUS_STRUCT_FLAG)
libomp_append(flags_local -Wno-unknown-pragmas LIBOMP_HAVE_WNO_UNKNOWN_PRAGMAS_FLAG)
libomp_append(flags_local -Wno-missing-field-initializers LIBOMP_HAVE_WNO_MISSING_FIELD_INITIALIZERS_FLAG)
libomp_append(flags_local -Wno-missing-braces LIBOMP_HAVE_WNO_MISSING_BRACES_FLAG)
libomp_append(flags_local -Wno-comment LIBOMP_HAVE_WNO_COMMENT_FLAG)
libomp_append(flags_local -Wno-self-assign LIBOMP_HAVE_WNO_SELF_ASSIGN_FLAG)
libomp_append(flags_local -Wno-vla-extension LIBOMP_HAVE_WNO_VLA_EXTENSION_FLAG)
libomp_append(flags_local -Wno-format-pedantic LIBOMP_HAVE_WNO_FORMAT_PEDANTIC_FLAG)
libomp_append(flags_local -Wno-frame-address LIBOMP_HAVE_WNO_FRAME_ADDRESS_FLAG)
libomp_append(flags_local -Wno-strict-aliasing LIBOMP_HAVE_WNO_STRICT_ALIASING_FLAG)
libomp_append(flags_local -Wstringop-overflow=0 LIBOMP_HAVE_WSTRINGOP_OVERFLOW_FLAG)
libomp_append(flags_local -Wno-stringop-truncation LIBOMP_HAVE_WNO_STRINGOP_TRUNCATION_FLAG)
libomp_append(flags_local -Wno-switch LIBOMP_HAVE_WNO_SWITCH_FLAG)
libomp_append(flags_local -Wno-uninitialized LIBOMP_HAVE_WNO_UNINITIALIZED_FLAG)
libomp_append(flags_local -Wno-unused-but-set-variable LIBOMP_HAVE_WNO_UNUSED_BUT_SET_VARIABLE_FLAG)
libomp_append(flags_local /GS LIBOMP_HAVE_GS_FLAG)
libomp_append(flags_local /EHsc LIBOMP_HAVE_EHSC_FLAG)
libomp_append(flags_local /Oy- LIBOMP_HAVE_OY__FLAG)
libomp_append(flags_local -mrtm LIBOMP_HAVE_MRTM_FLAG)
# Intel(R) C Compiler flags
libomp_append(flags_local /Qsafeseh LIBOMP_HAVE_QSAFESEH_FLAG)
libomp_append(flags_local -Qoption,cpp,--extended_float_types LIBOMP_HAVE_EXTENDED_FLOAT_TYPES_FLAG)
@@ -69,26 +61,7 @@ function(libomp_get_c_and_cxxflags_common flags)
libomp_append(flags_local -ftls-model=initial-exec LIBOMP_HAVE_FTLS_MODEL_FLAG)
libomp_append(flags_local "-opt-streaming-stores never" LIBOMP_HAVE_OPT_STREAMING_STORES_FLAG)
endif()
set(${flags} ${flags_local} PARENT_SCOPE)
endfunction()
# C compiler flags
function(libomp_get_cflags cflags)
set(cflags_local)
libomp_get_c_and_cxxflags_common(cflags_local)
# flags only for the C Compiler
libomp_append(cflags_local /TP LIBOMP_HAVE_TP_FLAG)
libomp_append(cflags_local "-x c++" LIBOMP_HAVE_X_CPP_FLAG)
set(cflags_local ${cflags_local} ${LIBOMP_CFLAGS})
libomp_setup_flags(cflags_local)
set(${cflags} ${cflags_local} PARENT_SCOPE)
endfunction()
# C++ compiler flags
function(libomp_get_cxxflags cxxflags)
set(cxxflags_local)
libomp_get_c_and_cxxflags_common(cxxflags_local)
set(cxxflags_local ${cxxflags_local} ${LIBOMP_CXXFLAGS})
set(cxxflags_local ${flags_local} ${LIBOMP_CXXFLAGS})
libomp_setup_flags(cxxflags_local)
set(${cxxflags} ${cxxflags_local} PARENT_SCOPE)
endfunction()
@@ -153,9 +126,13 @@ function(libomp_get_libflags libflags)
if(${IA32})
libomp_append(libflags_local -lirc_pic LIBOMP_HAVE_IRC_PIC_LIBRARY)
endif()
IF(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
if(${CMAKE_SYSTEM_NAME} MATCHES "DragonFly|FreeBSD")
libomp_append(libflags_local "-Wl,--no-as-needed" LIBOMP_HAVE_AS_NEEDED_FLAG)
libomp_append(libflags_local "-lm")
libomp_append(libflags_local "-Wl,--as-needed" LIBOMP_HAVE_AS_NEEDED_FLAG)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
libomp_append(libflags_local -lm)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
endif()
set(libflags_local ${libflags_local} ${LIBOMP_LIBFLAGS})
libomp_setup_flags(libflags_local)
set(${libflags} ${libflags_local} PARENT_SCOPE)
@@ -189,18 +166,6 @@ function(libomp_get_gdflags gdflags)
libomp_append(gdflags_local "-D stub" STUBS_LIBRARY)
libomp_append(gdflags_local "-D HAVE_QUAD" LIBOMP_USE_QUAD_PRECISION)
libomp_append(gdflags_local "-D USE_DEBUGGER" LIBOMP_USE_DEBUGGER)
if(${LIBOMP_OMP_VERSION} GREATER 50 OR ${LIBOMP_OMP_VERSION} EQUAL 50)
libomp_append(gdflags_local "-D OMP_50")
endif()
if(${LIBOMP_OMP_VERSION} GREATER 45 OR ${LIBOMP_OMP_VERSION} EQUAL 45)
libomp_append(gdflags_local "-D OMP_45")
endif()
if(${LIBOMP_OMP_VERSION} GREATER 40 OR ${LIBOMP_OMP_VERSION} EQUAL 40)
libomp_append(gdflags_local "-D OMP_40")
endif()
if(${LIBOMP_OMP_VERSION} GREATER 30 OR ${LIBOMP_OMP_VERSION} EQUAL 30)
libomp_append(gdflags_local "-D OMP_30")
endif()
if(${DEBUG_BUILD} OR ${RELWITHDEBINFO_BUILD})
libomp_append(gdflags_local "-D KMP_DEBUG")
endif()
+10 -5
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -171,11 +170,14 @@ add_custom_command(
add_custom_target(libomp-test-deps DEPENDS test-deps/.success)
set(libomp_expected_library_deps)
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(libomp_expected_library_deps libc.so.7 libthr.so.3)
set(libomp_expected_library_deps libc.so.7 libthr.so.3 libm.so.5)
libomp_append(libomp_expected_library_deps libhwloc.so.5 LIBOMP_USE_HWLOC)
elseif(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
set(libomp_expected_library_deps libc.so.12 libpthread.so.1 libm.so.0)
libomp_append(libomp_expected_library_deps libhwloc.so.5 LIBOMP_USE_HWLOC)
elseif(CMAKE_SYSTEM_NAME MATCHES "DragonFly")
set(libomp_expected_library_deps libc.so.8 libpthread.so.0 libm.so.4)
libomp_append(libomp_expected_library_deps libhwloc.so.5 LIBOMP_USE_HWLOC)
elseif(APPLE)
set(libomp_expected_library_deps /usr/lib/libSystem.B.dylib)
elseif(WIN32)
@@ -209,6 +211,9 @@ else()
elseif(${MIPS} OR ${MIPS64})
libomp_append(libomp_expected_library_deps libc.so.6)
libomp_append(libomp_expected_library_deps ld.so.1)
elseif(${RISCV64})
libomp_append(libomp_expected_library_deps libc.so.6)
libomp_append(libomp_expected_library_deps ld.so.1)
endif()
libomp_append(libomp_expected_library_deps libpthread.so.0 IF_FALSE STUBS_LIBRARY)
libomp_append(libomp_expected_library_deps libhwloc.so.5 LIBOMP_USE_HWLOC)
+5 -4
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -106,6 +105,8 @@ function(libomp_get_legal_arch return_arch_string)
set(${return_arch_string} "MIPS" PARENT_SCOPE)
elseif(${MIPS64})
set(${return_arch_string} "MIPS64" PARENT_SCOPE)
elseif(${RISCV64})
set(${return_arch_string} "RISCV64" PARENT_SCOPE)
else()
set(${return_arch_string} "${LIBOMP_ARCH}" PARENT_SCOPE)
libomp_warning_say("libomp_get_legal_arch(): Warning: Unknown architecture: Using ${LIBOMP_ARCH}")
+26 -33
View File
@@ -1,10 +1,9 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
@@ -46,39 +45,32 @@ function(libomp_check_architecture_flag flag retval)
set(${retval} ${${retval}} PARENT_SCOPE)
endfunction()
# Checking C, CXX, Linker Flags
# Checking CXX, Linker Flags
check_cxx_compiler_flag(-fno-exceptions LIBOMP_HAVE_FNO_EXCEPTIONS_FLAG)
check_cxx_compiler_flag(-fno-rtti LIBOMP_HAVE_FNO_RTTI_FLAG)
check_c_compiler_flag("-x c++" LIBOMP_HAVE_X_CPP_FLAG)
check_c_compiler_flag(-Wunused-function LIBOMP_HAVE_WNO_UNUSED_FUNCTION_FLAG)
check_c_compiler_flag(-Wunused-local-typedef LIBOMP_HAVE_WNO_UNUSED_LOCAL_TYPEDEF_FLAG)
check_c_compiler_flag(-Wunused-value LIBOMP_HAVE_WNO_UNUSED_VALUE_FLAG)
check_c_compiler_flag(-Wunused-variable LIBOMP_HAVE_WNO_UNUSED_VARIABLE_FLAG)
check_c_compiler_flag(-Wswitch LIBOMP_HAVE_WNO_SWITCH_FLAG)
check_c_compiler_flag(-Wcovered-switch-default LIBOMP_HAVE_WNO_COVERED_SWITCH_DEFAULT_FLAG)
check_c_compiler_flag(-Wdeprecated-register LIBOMP_HAVE_WNO_DEPRECATED_REGISTER_FLAG)
check_c_compiler_flag(-Wsign-compare LIBOMP_HAVE_WNO_SIGN_COMPARE_FLAG)
check_c_compiler_flag(-Wgnu-anonymous-struct LIBOMP_HAVE_WNO_GNU_ANONYMOUS_STRUCT_FLAG)
check_c_compiler_flag(-Wunknown-pragmas LIBOMP_HAVE_WNO_UNKNOWN_PRAGMAS_FLAG)
check_c_compiler_flag(-Wmissing-field-initializers LIBOMP_HAVE_WNO_MISSING_FIELD_INITIALIZERS_FLAG)
check_c_compiler_flag(-Wmissing-braces LIBOMP_HAVE_WNO_MISSING_BRACES_FLAG)
check_c_compiler_flag(-Wcomment LIBOMP_HAVE_WNO_COMMENT_FLAG)
check_c_compiler_flag(-Wself-assign LIBOMP_HAVE_WNO_SELF_ASSIGN_FLAG)
check_c_compiler_flag(-Wvla-extension LIBOMP_HAVE_WNO_VLA_EXTENSION_FLAG)
check_c_compiler_flag(-Wformat-pedantic LIBOMP_HAVE_WNO_FORMAT_PEDANTIC_FLAG)
check_c_compiler_flag(-Wstringop-overflow=0 LIBOMP_HAVE_WSTRINGOP_OVERFLOW_FLAG)
check_c_compiler_flag(-msse2 LIBOMP_HAVE_MSSE2_FLAG)
check_c_compiler_flag(-ftls-model=initial-exec LIBOMP_HAVE_FTLS_MODEL_FLAG)
check_cxx_compiler_flag(-Wno-class-memaccess LIBOMP_HAVE_WNO_CLASS_MEMACCESS_FLAG)
check_cxx_compiler_flag(-Wno-covered-switch-default LIBOMP_HAVE_WNO_COVERED_SWITCH_DEFAULT_FLAG)
check_cxx_compiler_flag(-Wno-frame-address LIBOMP_HAVE_WNO_FRAME_ADDRESS_FLAG)
check_cxx_compiler_flag(-Wno-strict-aliasing LIBOMP_HAVE_WNO_STRICT_ALIASING_FLAG)
check_cxx_compiler_flag(-Wstringop-overflow=0 LIBOMP_HAVE_WSTRINGOP_OVERFLOW_FLAG)
check_cxx_compiler_flag(-Wno-stringop-truncation LIBOMP_HAVE_WNO_STRINGOP_TRUNCATION_FLAG)
check_cxx_compiler_flag(-Wno-switch LIBOMP_HAVE_WNO_SWITCH_FLAG)
check_cxx_compiler_flag(-Wno-uninitialized LIBOMP_HAVE_WNO_UNINITIALIZED_FLAG)
check_cxx_compiler_flag(-Wno-unused-but-set-variable LIBOMP_HAVE_WNO_UNUSED_BUT_SET_VARIABLE_FLAG)
check_cxx_compiler_flag(-msse2 LIBOMP_HAVE_MSSE2_FLAG)
check_cxx_compiler_flag(-ftls-model=initial-exec LIBOMP_HAVE_FTLS_MODEL_FLAG)
libomp_check_architecture_flag(-mmic LIBOMP_HAVE_MMIC_FLAG)
libomp_check_architecture_flag(-m32 LIBOMP_HAVE_M32_FLAG)
if(WIN32)
# Check Windows MSVC style flags.
check_c_compiler_flag(/TP LIBOMP_HAVE_TP_FLAG)
check_cxx_compiler_flag(/EHsc LIBOMP_HAVE_EHSC_FLAG)
check_cxx_compiler_flag(/GS LIBOMP_HAVE_GS_FLAG)
check_cxx_compiler_flag(/Oy- LIBOMP_HAVE_Oy__FLAG)
check_cxx_compiler_flag(/arch:SSE2 LIBOMP_HAVE_ARCH_SSE2_FLAG)
check_cxx_compiler_flag(/Qsafeseh LIBOMP_HAVE_QSAFESEH_FLAG)
if(MSVC)
# Check Windows MSVC style flags.
check_cxx_compiler_flag(/EHsc LIBOMP_HAVE_EHSC_FLAG)
check_cxx_compiler_flag(/GS LIBOMP_HAVE_GS_FLAG)
check_cxx_compiler_flag(/Oy- LIBOMP_HAVE_Oy__FLAG)
check_cxx_compiler_flag(/arch:SSE2 LIBOMP_HAVE_ARCH_SSE2_FLAG)
check_cxx_compiler_flag(/Qsafeseh LIBOMP_HAVE_QSAFESEH_FLAG)
endif()
check_cxx_compiler_flag(-mrtm LIBOMP_HAVE_MRTM_FLAG)
# It is difficult to create a dummy masm assembly file
# and then check the MASM assembler to see if these flags exist and work,
# so we assume they do for Windows.
@@ -243,7 +235,8 @@ else()
# (LIBOMP_ARCH STREQUAL arm) OR
(LIBOMP_ARCH STREQUAL aarch64) OR
(LIBOMP_ARCH STREQUAL ppc64le) OR
(LIBOMP_ARCH STREQUAL ppc64))
(LIBOMP_ARCH STREQUAL ppc64) OR
(LIBOMP_ARCH STREQUAL riscv64))
AND # OS supported?
((WIN32 AND LIBOMP_HAVE_PSAPI) OR APPLE OR (NOT WIN32 AND LIBOMP_HAVE_WEAK_ATTRIBUTE)))
set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
+3 -4
View File
@@ -4,10 +4,9 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+25 -25
View File
@@ -1,19 +1,18 @@
#
#//===----------------------------------------------------------------------===//
#//
#// The LLVM Compiler Infrastructure
#//
#// This file is dual licensed under the MIT and the University of Illinois Open
#// Source Licenses. See LICENSE.txt for details.
#// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
#// See https://llvm.org/LICENSE.txt for license information.
#// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#//
#//===----------------------------------------------------------------------===//
#
# Configure omp.h, kmp_config.h and ompt.h if necessary
# Configure omp.h, kmp_config.h and omp-tools.h if necessary
configure_file(${LIBOMP_INC_DIR}/omp.h.var omp.h @ONLY)
configure_file(kmp_config.h.cmake kmp_config.h @ONLY)
if(${LIBOMP_OMPT_SUPPORT})
configure_file(${LIBOMP_INC_DIR}/ompt.h.var ompt.h @ONLY)
configure_file(${LIBOMP_INC_DIR}/omp-tools.h.var omp-tools.h @ONLY)
endif()
# Generate message catalog files: kmp_i18n_id.inc and kmp_i18n_default.inc
@@ -32,7 +31,7 @@ add_custom_command(
# Set the -D definitions for all sources
# UNICODE and _UNICODE are set in LLVM's CMake system. They affect the
# ittnotify code and should only be set when compiling ittnotify_static.c
# ittnotify code and should only be set when compiling ittnotify_static.cpp
# on Windows (done below).
# TODO: Fix the UNICODE usage in ittnotify code for Windows.
remove_definitions(-DUNICODE -D_UNICODE)
@@ -52,11 +51,10 @@ if(${LIBOMP_USE_HWLOC})
endif()
# Getting correct source files to build library
set(LIBOMP_CFILES)
set(LIBOMP_CXXFILES)
set(LIBOMP_ASMFILES)
if(${STUBS_LIBRARY})
set(LIBOMP_CFILES kmp_stub.cpp)
if(STUBS_LIBRARY)
set(LIBOMP_CXXFILES kmp_stub.cpp)
else()
# Get C++ files
set(LIBOMP_CXXFILES
@@ -74,7 +72,6 @@ else()
kmp_settings.cpp
kmp_str.cpp
kmp_tasking.cpp
kmp_taskq.cpp
kmp_threadprivate.cpp
kmp_utility.cpp
kmp_barrier.cpp
@@ -95,14 +92,12 @@ else()
libomp_append(LIBOMP_CXXFILES kmp_gsupport.cpp)
libomp_append(LIBOMP_ASMFILES z_Linux_asm.S) # Unix assembly file
endif()
libomp_append(LIBOMP_CFILES thirdparty/ittnotify/ittnotify_static.c LIBOMP_USE_ITT_NOTIFY)
libomp_append(LIBOMP_CXXFILES thirdparty/ittnotify/ittnotify_static.cpp LIBOMP_USE_ITT_NOTIFY)
libomp_append(LIBOMP_CXXFILES kmp_debugger.cpp LIBOMP_USE_DEBUGGER)
libomp_append(LIBOMP_CXXFILES kmp_stats.cpp LIBOMP_STATS)
libomp_append(LIBOMP_CXXFILES kmp_stats_timing.cpp LIBOMP_STATS)
if(${LIBOMP_OMP_VERSION} GREATER 40 OR ${LIBOMP_OMP_VERSION} EQUAL 40)
libomp_append(LIBOMP_CXXFILES kmp_taskdeps.cpp)
libomp_append(LIBOMP_CXXFILES kmp_cancel.cpp)
endif()
libomp_append(LIBOMP_CXXFILES kmp_taskdeps.cpp)
libomp_append(LIBOMP_CXXFILES kmp_cancel.cpp)
endif()
# Files common to stubs and normal library
libomp_append(LIBOMP_CXXFILES kmp_ftn_cdecl.cpp)
@@ -111,16 +106,14 @@ libomp_append(LIBOMP_CXXFILES kmp_version.cpp)
libomp_append(LIBOMP_CXXFILES ompt-general.cpp IF_TRUE LIBOMP_OMPT_SUPPORT)
libomp_append(LIBOMP_CXXFILES tsan_annotations.cpp IF_TRUE LIBOMP_TSAN_SUPPORT)
set(LIBOMP_SOURCE_FILES ${LIBOMP_CFILES} ${LIBOMP_CXXFILES} ${LIBOMP_ASMFILES})
set(LIBOMP_SOURCE_FILES ${LIBOMP_CXXFILES} ${LIBOMP_ASMFILES})
# For Windows, there is a resource file (.rc -> .res) that is also compiled
libomp_append(LIBOMP_SOURCE_FILES libomp.rc WIN32)
# Get compiler and assembler flags
libomp_get_cflags(LIBOMP_CONFIGURED_CFLAGS)
libomp_get_cxxflags(LIBOMP_CONFIGURED_CXXFLAGS)
libomp_get_asmflags(LIBOMP_CONFIGURED_ASMFLAGS)
# Set the compiler flags for each type of source
set_source_files_properties(${LIBOMP_CFILES} PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CFLAGS}")
set_source_files_properties(${LIBOMP_CXXFILES} PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CXXFLAGS}")
set_source_files_properties(${LIBOMP_ASMFILES} PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_ASMFLAGS}")
# Let the compiler handle the assembly files on Unix-like systems
@@ -195,12 +188,12 @@ if(WIN32)
libomp_append(LIBOMP_MASM_DEFINITIONS "-DOMPT_SUPPORT" IF_TRUE_1_0 LIBOMP_OMPT_SUPPORT)
libomp_list_to_string("${LIBOMP_MASM_DEFINITIONS}" LIBOMP_MASM_DEFINITIONS)
set_property(SOURCE z_Windows_NT-586_asm.asm APPEND_STRING PROPERTY COMPILE_FLAGS " ${LIBOMP_MASM_DEFINITIONS}")
set_source_files_properties(thirdparty/ittnotify/ittnotify_static.c PROPERTIES COMPILE_DEFINITIONS "UNICODE")
set_source_files_properties(thirdparty/ittnotify/ittnotify_static.cpp PROPERTIES COMPILE_DEFINITIONS "UNICODE")
# Create Windows import library
# the import library is "re-linked" to include kmp_import.cpp which prevents
# linking of both Visual Studio OpenMP and newly built OpenMP
set_source_files_properties(kmp_import.cpp PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CFLAGS}")
set_source_files_properties(kmp_import.cpp PROPERTIES COMPILE_FLAGS "${LIBOMP_CONFIGURED_CXXFLAGS}")
set(LIBOMP_IMP_LIB_FILE ${LIBOMP_LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX})
set(LIBOMP_GENERATED_IMP_LIB_FILENAME ${LIBOMP_LIB_FILE}${CMAKE_STATIC_LIBRARY_SUFFIX})
set_target_properties(omp PROPERTIES
@@ -241,6 +234,11 @@ if(${LIBOMP_FORTRAN_MODULES})
configure_file(${LIBOMP_INC_DIR}/omp_lib.h.var omp_lib.h @ONLY)
configure_file(${LIBOMP_INC_DIR}/omp_lib.f.var omp_lib.f @ONLY)
configure_file(${LIBOMP_INC_DIR}/omp_lib.f90.var omp_lib.f90 @ONLY)
# Workaround for gfortran to build modules with the
# omp_sched_monotonic integer parameter
if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
set(ADDITIONAL_Fortran_FLAGS "-fno-range-check")
endif()
add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod)
libomp_get_fflags(LIBOMP_CONFIGURED_FFLAGS)
if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
@@ -250,7 +248,8 @@ if(${LIBOMP_FORTRAN_MODULES})
endif()
add_custom_command(
OUTPUT omp_lib.mod omp_lib_kinds.mod
COMMAND ${CMAKE_Fortran_COMPILER} -c ${LIBOMP_CONFIGURED_FFLAGS} ${LIBOMP_FORTRAN_SOURCE_FILE}
COMMAND ${CMAKE_Fortran_COMPILER} -c ${ADDITIONAL_Fortran_FLAGS}
${LIBOMP_CONFIGURED_FFLAGS} ${LIBOMP_FORTRAN_SOURCE_FILE}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_FORTRAN_SOURCE_FILE}
${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
)
@@ -297,7 +296,7 @@ if(WIN32)
install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E copy \"${LIBOMP_LIB_FILE}\"
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/bin)")
install(CODE "execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E copy \"${LIBOMP_IMP_LIB_FILE}\"
\"${alias}${LIBOMP_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/${OPENMP_INSTALL_LIBDIR})")
\"${alias}${CMAKE_STATIC_LIBRARY_SUFFIX}\" WORKING_DIRECTORY \${CMAKE_INSTALL_PREFIX}/${OPENMP_INSTALL_LIBDIR})")
endforeach()
else()
@@ -319,7 +318,9 @@ install(
DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH}
)
if(${LIBOMP_OMPT_SUPPORT})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ompt.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH})
# install under legacy name ompt.h
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH} RENAME ompt.h)
endif()
if(${LIBOMP_FORTRAN_MODULES})
install(FILES
@@ -329,4 +330,3 @@ if(${LIBOMP_FORTRAN_MODULES})
DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH}
)
endif()

Some files were not shown because too many files have changed in this diff Show More