diff --git a/hipamd/Jenkinsfile b/hipamd/Jenkinsfile index 540e7e6689..6d37f10e3c 100644 --- a/hipamd/Jenkinsfile +++ b/hipamd/Jenkinsfile @@ -296,8 +296,53 @@ def docker_upload_dockerhub( String local_org, String image_name, String remote_ String build_config = 'Release' String job_name = env.JOB_NAME.toLowerCase( ) -// The following launches 2 builds in parallel: rocm-head and cuda-9.x -parallel rocm_head: +// The following launches 3 builds in parallel: rocm-head, rocm-1.9.x and cuda-9.x +parallel rocm_1_9: +{ + node('hip-rocm') + { + String hcc_ver = 'rocm-1.9.x' + String from_image = 'ci_test_nodes/rocm-1.9.x/ubuntu-16.04:latest' + String inside_args = '--device=/dev/kfd --device=/dev/dri --group-add=video' + + // Checkout source code, dependencies and version files + String source_hip_rel = checkout_and_version( hcc_ver ) + + // Create/reuse a docker image that represents the hip build environment + def hip_build_image = docker_build_image( hcc_ver, 'hip', '', source_hip_rel, from_image ) + + // Print system information for the log + hip_build_image.inside( inside_args ) + { + sh """#!/usr/bin/env bash + set -x + /opt/rocm/bin/rocm_agent_enumerator -t ALL + /opt/rocm/bin/hcc --version + """ + } + + // Conctruct a binary directory path based on build config + String build_hip_rel = build_directory_rel( build_config ); + + // Build hip inside of the build environment + docker_build_inside_image( hip_build_image, inside_args, hcc_ver, '', build_config, source_hip_rel, build_hip_rel ) + + // Clean docker build image + docker_clean_images( 'hip', docker_build_image_name( ) ) + + // After a successful build, upload a docker image of the results + /* + String hip_image_name = docker_upload_artifactory( hcc_ver, job_name, from_image, source_hip_rel, build_hip_rel ) + if( params.push_image_to_docker_hub ) + { + docker_upload_dockerhub( job_name, hip_image_name, 'rocm' ) + docker_clean_images( 'rocm', hip_image_name ) + } + docker_clean_images( job_name, hip_image_name ) + */ + } +}, +rocm_head: { node('hip-rocm') { diff --git a/hipamd/bin/hipcc b/hipamd/bin/hipcc index f22884ea1b..5942b20b8d 100755 --- a/hipamd/bin/hipcc +++ b/hipamd/bin/hipcc @@ -687,7 +687,11 @@ if($HIP_PLATFORM eq "hcc" or $HIP_PLATFORM eq "clang"){ $HIPCXXFLAGS .= " -D__HIP_ARCH_GFX900__=1 "; } if ($target_gfx906 eq 1) { - $HIPLDFLAGS .= " --amdgpu-target=gfx906"; + $GPU_ARCH_ARG = $GPU_ARCH_OPT . "gfx906"; + $HIPLDFLAGS .= $GPU_ARCH_ARG; + if ($HIP_PLATFORM eq 'clang') { + $HIPCXXFLAGS .= $GPU_ARCH_ARG;; + } $HIPCXXFLAGS .= " -D__HIP_ARCH_GFX906__=1 "; } } diff --git a/hipamd/hipify-clang/CMakeLists.txt b/hipamd/hipify-clang/CMakeLists.txt index a3952ba418..56de7c7904 100644 --- a/hipamd/hipify-clang/CMakeLists.txt +++ b/hipamd/hipify-clang/CMakeLists.txt @@ -23,7 +23,7 @@ set(CMAKE_CXX_COMPILER ${LLVM_TOOLS_BINARY_DIR}/clang++) set(CMAKE_C_COMPILER ${LLVM_TOOLS_BINARY_DIR}/clang) # Link against LLVM and CLANG libraries -target_link_libraries(hipify-clang +target_link_libraries(hipify-clang PRIVATE clangASTMatchers clangFrontend clangTooling @@ -48,11 +48,11 @@ target_link_libraries(hipify-clang LLVMCore) if(WIN32) - target_link_libraries(hipify-clang version) + target_link_libraries(hipify-clang PRIVATE version) endif() if ((LLVM_PACKAGE_VERSION VERSION_EQUAL "7") OR (LLVM_PACKAGE_VERSION VERSION_GREATER "7")) - target_link_libraries(hipify-clang clangToolingInclusions) + target_link_libraries(hipify-clang PRIVATE clangToolingInclusions) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") diff --git a/hipamd/hipify-clang/README.md b/hipamd/hipify-clang/README.md index 02bc9cfed0..ec46c7cb2f 100644 --- a/hipamd/hipify-clang/README.md +++ b/hipamd/hipify-clang/README.md @@ -30,11 +30,7 @@ ## Dependencies `hipify-clang` requires: -1. LLVM+CLANG of at least version 3.8.0, latest stable and recommended releases: - - 6.0.1 (linux and windows), - - 7.0.0 (linux only). +1. LLVM+CLANG of at least version 3.8.0, latest stable and recommended release: 6.0.1 (linux and windows). 2. CUDA at least version 7.5, latest supported release is 9.2. @@ -50,8 +46,8 @@ | 5.0.1 | 8.0 | | 5.0.2 | 8.0 | | 6.0.0 | 9.0 | -| 6.0.1 | 9.0 | -| 7.0.0 | 9.2 | linux only | +| **6.0.1** | **9.0** | **LATEST STABLE RELEASE** | +| 7.0.0 | 9.2 | windows is not supported, on linux there is a clang bug: https://bugs.llvm.org/show_bug.cgi?id=36384 | | | 10.0 | not yet supported | In most cases, you can get a suitable version of LLVM+CLANG with your package manager. @@ -77,10 +73,10 @@ cmake \ make -j install ``` -On Windows the following option should be specified for `cmake` at first place: `-G "Visual Studio 15 2017 Win64"` and after `cmake` the generated `hipify-clang.sln` should be built by `Visual Studio 15 2017` instead of `make`. +On Windows, the following option should be specified for `cmake` at first place: `-G "Visual Studio 15 2017 Win64"`; the generated `hipify-clang.sln` should be built by `Visual Studio 15 2017` instead of `make.` -Debug build type `-DCMAKE_BUILD_TYPE=Debug` is also supported and tested, `LLVM+CLANG` should be built in `Debug` mode as well. -64 bit build mode `-Thost=x64` is supported as well, `LLVM+CLANG` should be built (installed) in 64bit mode as well. +Debug build type `-DCMAKE_BUILD_TYPE=Debug` is also supported and tested; `LLVM+CLANG` should be built in `Debug` mode as well. +64 bit build mode `-Thost=x64` is supported as well; `LLVM+CLANG` should be built in 64bit mode as well. The binary can then be found at `./dist/bin/hipify-clang`. @@ -108,11 +104,11 @@ To run it: make -j install ``` - On Windows the following option should be specified for `cmake` at first place: `-G "Visual Studio 15 2017 Win64"` and after `cmake` the generated `LLVM.sln` should be built by `Visual Studio 15 2017` instead of `make`. + On Windows the following option should be specified for `cmake` at first place: `-G "Visual Studio 15 2017 Win64"`; the generated `LLVM.sln` should be built by `Visual Studio 15 2017` instead of `make`. 3. Ensure [`CUDA`](https://developer.nvidia.com/cuda-toolkit-archive) of minimum version 7.5 is installed. - * Having multiple CUDA installations in order to choose a concrete version the `DCUDA_TOOLKIT_ROOT_DIR` option should be specified: + * Having multiple CUDA installations, in order to choose a particular version the `DCUDA_TOOLKIT_ROOT_DIR` option should be specified: `-DCUDA_TOOLKIT_ROOT_DIR="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0"` @@ -127,7 +123,9 @@ To run it: `-DCUDA_DNN_ROOT_DIR=f:/CUDNN/cudnn-9.0-windows10-x64-v7.1` 5. Ensure [`python`](https://www.python.org/downloads) of minimum required version 2.7 is installed. + 6. Ensure `lit` and `FileCheck` are installed - these are distributed with LLVM. + * installing `lit` into `python` might be required: `python f:/LLVM/6.0.1/llvm/utils/lit/setup.py install`, @@ -139,7 +137,9 @@ To run it: `-DLLVM_EXTERNAL_LIT=f:/LLVM/6.0.1/build/Release/bin/llvm-lit.py`, where `f:/LLVM/6.0.1/build/Release` is LLVM build directory. + 7. Build with the `HIPIFY_CLANG_TESTS` option turned on: -DHIPIFY_CLANG_TESTS=1. + 8. `make test-hipify` On Windows after `cmake` the project `test-hipify` in the generated `hipify-clang.sln` should be built by `Visual Studio 15 2017` instead of `make test-hipify`. @@ -178,7 +178,7 @@ A corresponding successful output: -- - CMake module path: F:/LLVM/6.0.1/dist/lib/cmake/llvm -- - Include path : F:/LLVM/6.0.1/dist/include -- - Binary path : F:/LLVM/6.0.1/dist/bin --- Found PythonInterp: C:/Program Files/Python36/python.exe (found suitable version "3.6.4", minimum required is "2.7") +-- Found PythonInterp: C:/Program Files/Python36/python.exe (found suitable version "3.6.4", minimum required is "3.6") -- Found lit: C:/Program Files/Python36/Scripts/lit.exe -- Found FileCheck: F:/LLVM/6.0.1/dist/bin/FileCheck.exe -- Found CUDA: C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0 (found version "9.0") diff --git a/hipamd/include/hip/hcc_detail/device_functions.h b/hipamd/include/hip/hcc_detail/device_functions.h index 42927e3246..7b0a13e83a 100644 --- a/hipamd/include/hip/hcc_detail/device_functions.h +++ b/hipamd/include/hip/hcc_detail/device_functions.h @@ -297,9 +297,16 @@ float __shfl(float var, int src_lane, int width = warpSize) { __device__ inline double __shfl(double var, int src_lane, int width = warpSize) { - __u tmp; tmp.f = (float) var; - tmp.i = __shfl(tmp.i, src_lane, width); - return (double) tmp.f; + static_assert(sizeof(double) == 2 * sizeof(int), ""); + static_assert(sizeof(double) == sizeof(uint64_t), ""); + + int tmp[2]; __builtin_memcpy(tmp, &var, sizeof(tmp)); + tmp[0] = __shfl(tmp[0], src_lane, width); + tmp[1] = __shfl(tmp[1], src_lane, width); + + uint64_t tmp0 = (static_cast(tmp[1]) << 32ull) | static_cast(tmp[0]); + double tmp1; __builtin_memcpy(&tmp1, &tmp0, sizeof(tmp0)); + return tmp1; } __device__ @@ -327,9 +334,16 @@ float __shfl_up(float var, unsigned int lane_delta, int width = warpSize) { __device__ inline double __shfl_up(double var, unsigned int lane_delta, int width = warpSize) { - __u tmp; tmp.f = (float) var; - tmp.i = __shfl_up(tmp.i, lane_delta, width); - return (double) tmp.f; + static_assert(sizeof(double) == 2 * sizeof(int), ""); + static_assert(sizeof(double) == sizeof(uint64_t), ""); + + int tmp[2]; __builtin_memcpy(tmp, &var, sizeof(tmp)); + tmp[0] = __shfl_up(tmp[0], lane_delta, width); + tmp[1] = __shfl_up(tmp[1], lane_delta, width); + + uint64_t tmp0 = (static_cast(tmp[1]) << 32ull) | static_cast(tmp[0]); + double tmp1; __builtin_memcpy(&tmp1, &tmp0, sizeof(tmp0)); + return tmp1; } __device__ @@ -357,9 +371,16 @@ float __shfl_down(float var, unsigned int lane_delta, int width = warpSize) { __device__ inline double __shfl_down(double var, unsigned int lane_delta, int width = warpSize) { - __u tmp; tmp.f = (float) var; - tmp.i = __shfl_down(tmp.i, lane_delta, width); - return (double) tmp.f; + static_assert(sizeof(double) == 2 * sizeof(int), ""); + static_assert(sizeof(double) == sizeof(uint64_t), ""); + + int tmp[2]; __builtin_memcpy(tmp, &var, sizeof(tmp)); + tmp[0] = __shfl_down(tmp[0], lane_delta, width); + tmp[1] = __shfl_down(tmp[1], lane_delta, width); + + uint64_t tmp0 = (static_cast(tmp[1]) << 32ull) | static_cast(tmp[0]); + double tmp1; __builtin_memcpy(&tmp1, &tmp0, sizeof(tmp0)); + return tmp1; } __device__ @@ -387,9 +408,16 @@ float __shfl_xor(float var, int lane_mask, int width = warpSize) { __device__ inline double __shfl_xor(double var, int lane_mask, int width = warpSize) { - __u tmp; tmp.f = (float) var; - tmp.i = __shfl_xor(tmp.i, lane_mask, width); - return (double) tmp.f; + static_assert(sizeof(double) == 2 * sizeof(int), ""); + static_assert(sizeof(double) == sizeof(uint64_t), ""); + + int tmp[2]; __builtin_memcpy(tmp, &var, sizeof(tmp)); + tmp[0] = __shfl_xor(tmp[0], lane_mask, width); + tmp[1] = __shfl_xor(tmp[1], lane_mask, width); + + uint64_t tmp0 = (static_cast(tmp[1]) << 32ull) | static_cast(tmp[0]); + double tmp1; __builtin_memcpy(&tmp1, &tmp0, sizeof(tmp0)); + return tmp1; } #define MASK1 0x00ff00ff @@ -752,6 +780,80 @@ void *__amdgcn_get_dynamicgroupbaseptr() { return __get_dynamicgroupbaseptr(); } +#if defined(__HCC__) && (__hcc_minor__ < 3) +// hip.amdgcn.bc - sync threads +#define __CLK_LOCAL_MEM_FENCE 0x01 +typedef unsigned __cl_mem_fence_flags; + +typedef enum __memory_scope { + __memory_scope_work_item = __OPENCL_MEMORY_SCOPE_WORK_ITEM, + __memory_scope_work_group = __OPENCL_MEMORY_SCOPE_WORK_GROUP, + __memory_scope_device = __OPENCL_MEMORY_SCOPE_DEVICE, + __memory_scope_all_svm_devices = __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES, + __memory_scope_sub_group = __OPENCL_MEMORY_SCOPE_SUB_GROUP +} __memory_scope; + +// enum values aligned with what clang uses in EmitAtomicExpr() +typedef enum __memory_order +{ + __memory_order_relaxed = __ATOMIC_RELAXED, + __memory_order_acquire = __ATOMIC_ACQUIRE, + __memory_order_release = __ATOMIC_RELEASE, + __memory_order_acq_rel = __ATOMIC_ACQ_REL, + __memory_order_seq_cst = __ATOMIC_SEQ_CST +} __memory_order; + +__device__ +inline +static void +__atomic_work_item_fence(__cl_mem_fence_flags flags, __memory_order order, __memory_scope scope) +{ + // We're tying global-happens-before and local-happens-before together as does HSA + if (order != __memory_order_relaxed) { + switch (scope) { + case __memory_scope_work_item: + break; + case __memory_scope_sub_group: + switch (order) { + case __memory_order_relaxed: break; + case __memory_order_acquire: __llvm_fence_acq_sg(); break; + case __memory_order_release: __llvm_fence_rel_sg(); break; + case __memory_order_acq_rel: __llvm_fence_ar_sg(); break; + case __memory_order_seq_cst: __llvm_fence_sc_sg(); break; + } + break; + case __memory_scope_work_group: + switch (order) { + case __memory_order_relaxed: break; + case __memory_order_acquire: __llvm_fence_acq_wg(); break; + case __memory_order_release: __llvm_fence_rel_wg(); break; + case __memory_order_acq_rel: __llvm_fence_ar_wg(); break; + case __memory_order_seq_cst: __llvm_fence_sc_wg(); break; + } + break; + case __memory_scope_device: + switch (order) { + case __memory_order_relaxed: break; + case __memory_order_acquire: __llvm_fence_acq_dev(); break; + case __memory_order_release: __llvm_fence_rel_dev(); break; + case __memory_order_acq_rel: __llvm_fence_ar_dev(); break; + case __memory_order_seq_cst: __llvm_fence_sc_dev(); break; + } + break; + case __memory_scope_all_svm_devices: + switch (order) { + case __memory_order_relaxed: break; + case __memory_order_acquire: __llvm_fence_acq_sys(); break; + case __memory_order_release: __llvm_fence_rel_sys(); break; + case __memory_order_acq_rel: __llvm_fence_ar_sys(); break; + case __memory_order_seq_cst: __llvm_fence_sc_sys(); break; + } + break; + } + } +} +#endif + // Memory Fence Functions __device__ inline diff --git a/hipamd/include/hip/hcc_detail/device_library_decls.h b/hipamd/include/hip/hcc_detail/device_library_decls.h index 2a0b968fe3..2bf3c8cc51 100644 --- a/hipamd/include/hip/hcc_detail/device_library_decls.h +++ b/hipamd/include/hip/hcc_detail/device_library_decls.h @@ -65,6 +65,29 @@ extern "C" __device__ __attribute__((const)) float __ocml_fmax_f32(float, float) __device__ inline static __local void* __to_local(unsigned x) { return (__local void*)x; } #endif //__HIP_DEVICE_COMPILE__ +#if defined(__HCC__) && (__hcc_minor__ < 3) +// __llvm_fence* functions from device-libs/irif/src/fence.ll +extern "C" __device__ void __llvm_fence_acq_sg(void); +extern "C" __device__ void __llvm_fence_acq_wg(void); +extern "C" __device__ void __llvm_fence_acq_dev(void); +extern "C" __device__ void __llvm_fence_acq_sys(void); + +extern "C" __device__ void __llvm_fence_rel_sg(void); +extern "C" __device__ void __llvm_fence_rel_wg(void); +extern "C" __device__ void __llvm_fence_rel_dev(void); +extern "C" __device__ void __llvm_fence_rel_sys(void); + +extern "C" __device__ void __llvm_fence_ar_sg(void); +extern "C" __device__ void __llvm_fence_ar_wg(void); +extern "C" __device__ void __llvm_fence_ar_dev(void); +extern "C" __device__ void __llvm_fence_ar_sys(void); + + +extern "C" __device__ void __llvm_fence_sc_sg(void); +extern "C" __device__ void __llvm_fence_sc_wg(void); +extern "C" __device__ void __llvm_fence_sc_dev(void); +extern "C" __device__ void __llvm_fence_sc_sys(void); +#else // Using hip.amdgcn.bc - sync threads #define __CLK_LOCAL_MEM_FENCE 0x01 typedef unsigned __cl_mem_fence_flags; @@ -90,5 +113,6 @@ typedef enum __memory_order // Linked from hip.amdgcn.bc extern "C" __device__ void __atomic_work_item_fence(__cl_mem_fence_flags, __memory_order, __memory_scope); +#endif #endif diff --git a/hipamd/src/hip_stream.cpp b/hipamd/src/hip_stream.cpp index 1e239cb2fc..2268a203dd 100644 --- a/hipamd/src/hip_stream.cpp +++ b/hipamd/src/hip_stream.cpp @@ -31,12 +31,21 @@ THE SOFTWARE. //------------------------------------------------------------------------------------------------- // Stream // +#if defined(__HCC__) && (__hcc_minor__ < 3) +enum queue_priority +{ + priority_high = 0, + priority_normal = 0, + priority_low = 0 +}; +#else enum queue_priority { priority_high = Kalmar::priority_high, priority_normal = Kalmar::priority_normal, priority_low = Kalmar::priority_low }; +#endif //--- hipError_t ihipStreamCreate(hipStream_t* stream, unsigned int flags, int priority) { @@ -59,7 +68,11 @@ hipError_t ihipStreamCreate(hipStream_t* stream, unsigned int flags, int priorit // Obtain mutex access to the device critical data, release by destructor LockedAccessor_CtxCrit_t ctxCrit(ctx->criticalData()); +#if defined(__HCC__) && (__hcc_minor__ < 3) + auto istream = new ihipStream_t(ctx, acc.create_view(), flags); +#else auto istream = new ihipStream_t(ctx, acc.create_view(Kalmar::execute_in_order, Kalmar::queuing_mode_automatic, (Kalmar::queue_priority)priority), flags); +#endif ctxCrit->addStream(istream); *stream = istream; @@ -223,8 +236,12 @@ hipError_t hipStreamGetPriority(hipStream_t stream, int* priority) { } else if (stream == hipStreamNull) { return ihipLogStatus(hipErrorInvalidResourceHandle); } else { +#if defined(__HCC__) && (__hcc_minor__ < 3) + *priority = 0; +#else LockedAccessor_StreamCrit_t crit(stream->_criticalData); *priority = crit->_av.get_queue_priority(); +#endif return ihipLogStatus(hipSuccess); } }