| //===----------------------------------------------------------------------===// |
| // |
| // 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 __OMPX_H |
| #define __OMPX_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| int omp_get_ancestor_thread_num(int); |
| int omp_get_team_size(int); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| /// Target kernel language extensions |
| /// |
| /// These extensions exist for the host to allow fallback implementations, |
| /// however, they cannot be arbitrarily composed with OpenMP. If the rules of |
| /// the kernel language are followed, the host fallbacks should behave as |
| /// expected since the kernel is represented as 3 sequential outer loops, one |
| /// for each grid dimension, and three (nested) parallel loops, one for each |
| /// block dimension. This fallback is not supposed to be optimal and should be |
| /// configurable by the user. |
| /// |
| ///{ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| enum { |
| ompx_relaxed = __ATOMIC_RELAXED, |
| ompx_aquire = __ATOMIC_ACQUIRE, |
| ompx_release = __ATOMIC_RELEASE, |
| ompx_acq_rel = __ATOMIC_ACQ_REL, |
| ompx_seq_cst = __ATOMIC_SEQ_CST, |
| }; |
| |
| enum { |
| ompx_dim_x = 0, |
| ompx_dim_y = 1, |
| ompx_dim_z = 2, |
| }; |
| |
| /// ompx_{thread,block}_{id,dim} |
| ///{ |
| #pragma omp begin declare variant match(device = {kind(cpu)}) |
| #define _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(NAME, VALUE) \ |
| static inline int ompx_##NAME(int Dim) { return VALUE; } |
| |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(thread_id, |
| omp_get_ancestor_thread_num(Dim + 1)) |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(block_dim, omp_get_team_size(Dim + 1)) |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(block_id, 0) |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(grid_dim, 1) |
| #undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C |
| ///} |
| |
| /// ompx_{sync_block}_{,divergent} |
| ///{ |
| #define _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(RETTY, NAME, ARGS, BODY) \ |
| static inline RETTY ompx_##NAME(ARGS) { BODY; } |
| |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(void, sync_block, int Ordering, |
| _Pragma("omp barrier")); |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(void, sync_block_acq_rel, void, |
| ompx_sync_block(ompx_acq_rel)); |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(void, sync_block_divergent, int Ordering, |
| ompx_sync_block(Ordering)); |
| #undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C |
| ///} |
| |
| #pragma omp end declare variant |
| |
| /// ompx_{sync_block}_{,divergent} |
| ///{ |
| #define _TGT_KERNEL_LANGUAGE_DECL_SYNC_C(RETTY, NAME, ARGS) \ |
| RETTY ompx_##NAME(ARGS); |
| |
| _TGT_KERNEL_LANGUAGE_DECL_SYNC_C(void, sync_block, int Ordering); |
| _TGT_KERNEL_LANGUAGE_DECL_SYNC_C(void, sync_block_acq_rel, void); |
| _TGT_KERNEL_LANGUAGE_DECL_SYNC_C(void, sync_block_divergent, int Ordering); |
| #undef _TGT_KERNEL_LANGUAGE_DECL_SYNC_C |
| ///} |
| |
| /// ompx_{thread,block}_{id,dim}_{x,y,z} |
| ///{ |
| #define _TGT_KERNEL_LANGUAGE_DECL_GRID_C(NAME) \ |
| int ompx_##NAME(int Dim); \ |
| static inline int ompx_##NAME##_x() { return ompx_##NAME(ompx_dim_x); } \ |
| static inline int ompx_##NAME##_y() { return ompx_##NAME(ompx_dim_y); } \ |
| static inline int ompx_##NAME##_z() { return ompx_##NAME(ompx_dim_z); } |
| |
| _TGT_KERNEL_LANGUAGE_DECL_GRID_C(thread_id) |
| _TGT_KERNEL_LANGUAGE_DECL_GRID_C(block_dim) |
| _TGT_KERNEL_LANGUAGE_DECL_GRID_C(block_id) |
| _TGT_KERNEL_LANGUAGE_DECL_GRID_C(grid_dim) |
| #undef _TGT_KERNEL_LANGUAGE_DECL_GRID_C |
| ///} |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #ifdef __cplusplus |
| |
| namespace ompx { |
| |
| enum { |
| dim_x = ompx_dim_x, |
| dim_y = ompx_dim_y, |
| dim_z = ompx_dim_z, |
| }; |
| |
| enum { |
| relaxed = ompx_relaxed , |
| aquire = ompx_aquire, |
| release = ompx_release, |
| acc_rel = ompx_acq_rel, |
| seq_cst = ompx_seq_cst, |
| }; |
| |
| /// ompx::{thread,block}_{id,dim}_{,x,y,z} |
| ///{ |
| #define _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(NAME) \ |
| static inline int NAME(int Dim) noexcept { return ompx_##NAME(Dim); } \ |
| static inline int NAME##_x() noexcept { return NAME(ompx_dim_x); } \ |
| static inline int NAME##_y() noexcept { return NAME(ompx_dim_y); } \ |
| static inline int NAME##_z() noexcept { return NAME(ompx_dim_z); } |
| |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(thread_id) |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(block_dim) |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(block_id) |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(grid_dim) |
| #undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX |
| ///} |
| |
| /// ompx_{sync_block}_{,divergent} |
| ///{ |
| #define _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX(RETTY, NAME, ARGS, CALL_ARGS) \ |
| static inline RETTY NAME(ARGS) { \ |
| return ompx_##NAME(CALL_ARGS); \ |
| } |
| |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX(void, sync_block, int Ordering = acc_rel, |
| Ordering); |
| _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX(void, sync_block_divergent, |
| int Ordering = acc_rel, Ordering); |
| #undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX |
| ///} |
| |
| } // namespace ompx |
| #endif |
| |
| ///} |
| |
| #endif /* __OMPX_H */ |