1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef __OMPX_H
10#define __OMPX_H
11
12#ifdef __cplusplus
13extern "C" {
14#endif
15
16int omp_get_ancestor_thread_num(int);
17int omp_get_team_size(int);
18
19#ifdef __cplusplus
20}
21#endif
22
23/// Target kernel language extensions
24///
25/// These extensions exist for the host to allow fallback implementations,
26/// however, they cannot be arbitrarily composed with OpenMP. If the rules of
27/// the kernel language are followed, the host fallbacks should behave as
28/// expected since the kernel is represented as 3 sequential outer loops, one
29/// for each grid dimension, and three (nested) parallel loops, one for each
30/// block dimension. This fallback is not supposed to be optimal and should be
31/// configurable by the user.
32///
33///{
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39enum {
40  ompx_relaxed = __ATOMIC_RELAXED,
41  ompx_aquire = __ATOMIC_ACQUIRE,
42  ompx_release = __ATOMIC_RELEASE,
43  ompx_acq_rel = __ATOMIC_ACQ_REL,
44  ompx_seq_cst = __ATOMIC_SEQ_CST,
45};
46
47enum {
48  ompx_dim_x = 0,
49  ompx_dim_y = 1,
50  ompx_dim_z = 2,
51};
52
53/// ompx_{thread,block}_{id,dim}
54///{
55#pragma omp begin declare variant match(device = {kind(cpu)})
56#define _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(NAME, VALUE)                     \
57  static inline int ompx_##NAME(int Dim) { return VALUE; }
58
59_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(thread_id,
60                                      omp_get_ancestor_thread_num(Dim + 1))
61_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(block_dim, omp_get_team_size(Dim + 1))
62_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(block_id, 0)
63_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C(grid_dim, 1)
64#undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_C
65///}
66
67/// ompx_{sync_block}_{,divergent}
68///{
69#define _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(RETTY, NAME, ARGS, BODY)         \
70  static inline RETTY ompx_##NAME(ARGS) { BODY; }
71
72_TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(void, sync_block, int Ordering,
73                                      _Pragma("omp barrier"));
74_TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(void, sync_block_acq_rel, void,
75                                      ompx_sync_block(ompx_acq_rel));
76_TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C(void, sync_block_divergent, int Ordering,
77                                      ompx_sync_block(Ordering));
78#undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_C
79///}
80
81#pragma omp end declare variant
82
83/// ompx_{sync_block}_{,divergent}
84///{
85#define _TGT_KERNEL_LANGUAGE_DECL_SYNC_C(RETTY, NAME, ARGS)         \
86  RETTY ompx_##NAME(ARGS);
87
88_TGT_KERNEL_LANGUAGE_DECL_SYNC_C(void, sync_block, int Ordering);
89_TGT_KERNEL_LANGUAGE_DECL_SYNC_C(void, sync_block_acq_rel, void);
90_TGT_KERNEL_LANGUAGE_DECL_SYNC_C(void, sync_block_divergent, int Ordering);
91#undef _TGT_KERNEL_LANGUAGE_DECL_SYNC_C
92///}
93
94/// ompx_{thread,block}_{id,dim}_{x,y,z}
95///{
96#define _TGT_KERNEL_LANGUAGE_DECL_GRID_C(NAME)                                 \
97  int ompx_##NAME(int Dim);                                                    \
98  static inline int ompx_##NAME##_x() { return ompx_##NAME(ompx_dim_x); }      \
99  static inline int ompx_##NAME##_y() { return ompx_##NAME(ompx_dim_y); }      \
100  static inline int ompx_##NAME##_z() { return ompx_##NAME(ompx_dim_z); }
101
102_TGT_KERNEL_LANGUAGE_DECL_GRID_C(thread_id)
103_TGT_KERNEL_LANGUAGE_DECL_GRID_C(block_dim)
104_TGT_KERNEL_LANGUAGE_DECL_GRID_C(block_id)
105_TGT_KERNEL_LANGUAGE_DECL_GRID_C(grid_dim)
106#undef _TGT_KERNEL_LANGUAGE_DECL_GRID_C
107///}
108
109#ifdef __cplusplus
110}
111#endif
112
113#ifdef __cplusplus
114
115namespace ompx {
116
117enum {
118  dim_x = ompx_dim_x,
119  dim_y = ompx_dim_y,
120  dim_z = ompx_dim_z,
121};
122
123enum {
124  relaxed = ompx_relaxed ,
125  aquire = ompx_aquire,
126  release = ompx_release,
127  acc_rel = ompx_acq_rel,
128  seq_cst = ompx_seq_cst,
129};
130
131/// ompx::{thread,block}_{id,dim}_{,x,y,z}
132///{
133#define _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(NAME)                          \
134  static inline int NAME(int Dim) noexcept { return ompx_##NAME(Dim); }        \
135  static inline int NAME##_x() noexcept { return NAME(ompx_dim_x); }           \
136  static inline int NAME##_y() noexcept { return NAME(ompx_dim_y); }           \
137  static inline int NAME##_z() noexcept { return NAME(ompx_dim_z); }
138
139_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(thread_id)
140_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(block_dim)
141_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(block_id)
142_TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX(grid_dim)
143#undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_GRID_CXX
144///}
145
146/// ompx_{sync_block}_{,divergent}
147///{
148#define _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX(RETTY, NAME, ARGS, CALL_ARGS)  \
149  static inline RETTY NAME(ARGS) {               \
150    return ompx_##NAME(CALL_ARGS);                                             \
151  }
152
153_TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX(void, sync_block, int Ordering = acc_rel,
154                                        Ordering);
155_TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX(void, sync_block_divergent,
156                                        int Ordering = acc_rel, Ordering);
157#undef _TGT_KERNEL_LANGUAGE_HOST_IMPL_SYNC_CXX
158///}
159
160} // namespace ompx
161#endif
162
163///}
164
165#endif /* __OMPX_H */
166