1 /*
2  * Copyright (c) 2015-2019, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #ifndef LLMPUTIL_H_
19 #define LLMPUTIL_H_
20 
21 /** \file
22  *  \brief OpenMP utility routines for LLVM compilers
23  */
24 
25 #include "gbldefs.h"
26 #include "global.h"
27 #include "symtab.h"
28 
29 /** Uplevel data structure containing a list of shared variables for the region
30  * nest that this uplevel belongs to.  The shared variables in this structure
31  * are represented as a list of unique sptrs.
32  */
33 typedef struct {
34   int *vals;      /* Array containing shared var sptrs */
35   int vals_size;  /* Total allocated slots in vals */
36   int vals_count; /* Traditionally "available" or vals_avl */
37   DTYPE dtype;    ///< The true dtype containing fields and their offsets
38   SPTR parent;    /* sptr of its parent */
39   /* TODO: Consider using a hashset to speed-unique lookup */
40 } LLUplevel;
41 
42 /** First private variable:
43  * This information is necessary to generate code that allows a particular task
44  * to know which variables are stored in its allocated memory (task memory).
45  * First privates for the task have to be stored in that memory.
46  */
47 typedef struct _llprivate_t {
48   int shared_sptr;  /**< Represents the caller's copy */
49   int private_sptr; /**< Represents the callee's copy (local) */
50 } LLFirstPrivate;
51 
52 /// Task data structure containing a list of private variables for the task.
53 typedef struct {
54   int scope_sptr;        /**< Outlined task's scope sptr (BMPSCOPE ST_BLOCK) */
55   int task_sptr;         /**< Outlined function representing the task */
56   LLFirstPrivate *privs; /**< Array of private sptrs for this task */
57   int privs_count;
58   int privs_size;
59   int actual_size; /**< Bytes in task: First priv size + base task size */
60 } LLTask;
61 
62 /// Data attributes for each data reference used in an OpenMP target region.
63 typedef enum {
64   // No flags
65     OMP_TGT_MAPTYPE_NONE            = 0x000,
66   // copy data from host to device
67     OMP_TGT_MAPTYPE_TO              = 0x001,
68   // copy data from device to host
69     OMP_TGT_MAPTYPE_FROM            = 0x002,
70   // copy regardless of the reference count
71     OMP_TGT_MAPTYPE_ALWAYS          = 0x004,
72   // force unmapping of data
73     OMP_TGT_MAPTYPE_DELETE          = 0x008,
74   // map the pointer as well as the pointee
75     OMP_TGT_MAPTYPE_PTR_AND_OBJ     = 0x010,
76   // pass device base address to kernel
77     OMP_TGT_MAPTYPE_TARGET_PARAM    = 0x020,
78   // return base device address of mapped data
79     OMP_TGT_MAPTYPE_RETURN_PARAM    = 0x040,
80   // private variable - not mapped
81     OMP_TGT_MAPTYPE_PRIVATE         = 0x080,
82   // copy by value - not mapped
83     OMP_TGT_MAPTYPE_LITERAL         = 0x100,
84   // mapping is implicit
85     OMP_TGT_MAPTYPE_IMPLICIT        = 0x200,
86   // member of struct, member given by 4 MSBs - 1
87     OMP_TGT_MAPTYPE_MEMBER_OF       = 0xffff000000000000
88 } tgt_map_type;
89 
90 
91 /* The modes of target related regions. */
92 typedef enum {
93   mode_none_target,
94   mode_target,
95   mode_target_teams,
96   mode_target_teams_distribute,
97   mode_target_teams_distribute_simd,
98   mode_target_teams_distribute_parallel_for,
99   mode_target_teams_distribute_parallel_for_simd,
100   mode_target_parallel,
101   mode_target_parallel_for,
102   mode_target_parallel_for_simd,
103   mode_target_data_enter_region,
104   mode_target_data_exit_region,
105   mode_target_data_region,
106   mode_outlinedfunc_teams,
107   mode_outlinedfunc_parallel,
108   mode_targetupdate_begin,
109   mode_targetupdate_end,
110 } OMP_TARGET_MODE;
111 
112 bool is_omp_mode_target(OMP_TARGET_MODE mode);
113 
114 /* The name of the modes of target related regions. */
115 static const char *omp_target_mode_names[] = {
116                                     "None target",
117                                     "target",
118                                     "target teams",
119                                     "target teams distribute",
120                                     "target teams distribute simd",
121                                     "target teams distribute parallel for",
122                                     "target teams distribute parallel for simd",
123                                     "target parallel",
124                                     "target parallel for",
125                                     "target parallel for simd",
126                                     "target data enter",
127                                     "target data exit",
128                                     "target data",
129                                     "outlined teams region",
130                                     "outlined parallel region",
131                                     "target update begin",
132                                     "target update end" };
133 
134 
135 /* Obtain a previously created task object, where scope_sptr is the BMPSCOPE
136  * scope sptr containing the task.
137  */
138 extern LLTask *llmp_get_task(int scope_sptr);
139 
140 /* Return the task base size without any private values being stored. */
141 extern int llmp_task_get_base_task_size(void);
142 
143 /* Return the task's total size including task metadata and priv vars */
144 extern int llmp_task_get_size(LLTask *task);
145 
146 /* Set the task function sptr */
147 extern void llmp_task_set_fnsptr(LLTask *task, int task_sptr);
148 
149 /* Return a task a object associated to 'task_sptr' */
150 extern LLTask *llmp_task_get_by_fnsptr(int task_sptr);
151 
152 /* Returns the sptr of the 'private' (local to the callee) copy of the
153  * private variable represented by 'sptr'.
154  */
155 extern int llmp_task_get_private(const LLTask *task, int sptr, int incl);
156 
157 /// \brief Uniquely add a shared variable
158 int llmp_add_shared_var(LLUplevel *up, int shared_sptr);
159 
160 /// \brief Return a new key (index) into our table of all uplevels
161 int llmp_get_next_key(void);
162 
163 /**
164    \brief ...
165  */
166 int llmp_task_add_loopvar(LLTask *task, int num, DTYPE dtype);
167 
168 /**
169    \brief Add a private sptr to the task object.
170    priv:   sptr to the private copy of the private variable.
171            ADDRESSP is called to set the offset to the kmpc task
172            object where this private data will live during program
173            execution.
174  /
175  */
176 int llmp_task_add_private(LLTask *task, int shared_sptr, SPTR private_sptr);
177 
178 /**
179    \brief ...
180  */
181 int llmp_task_get_base_task_size(void);
182 
183 /**
184    \brief ...
185  */
186 int llmp_task_get_private(const LLTask *task, int sptr, int encl);
187 
188 /**
189    \brief ...
190  */
191 INT llmp_task_get_privoff(int sptr, const LLTask *task);
192 
193 /**
194    \brief ...
195  */
196 int llmp_task_get_size(LLTask *task);
197 
198 /**
199    \brief ...
200  */
201 int llmp_uplevel_has_parent(int uplevel);
202 
203 /**
204    \brief Create task object that can be searched for later using \p scope_sptr
205    \param scope_sptr ...
206  */
207 LLTask *llmp_create_task(int scope_sptr);
208 
209 /**
210    \brief ...
211  */
212 LLTask *llmp_get_task(int scope_sptr);
213 
214 /**
215    \brief ...
216  */
217 LLTask *llmp_task_get_by_fnsptr(int task_sptr);
218 
219 /// \brief Retrieve an LLUplevel instance by key
220 LLUplevel *llmp_create_uplevel_bykey(int key);
221 
222 /**
223    \brief Create an LLUplevel instance
224    \param stblock_sptr Block where this region nest begins.
225    This is used as a key into the global list of all uplevels.
226  */
227 LLUplevel *llmp_create_uplevel(int uplevel_sptr);
228 
229 /// \brief Obtain a previously created uplevel
230 LLUplevel *llmp_get_uplevel(int uplevel_sptr);
231 
232 /** Return an uplevel pointer if it has an entry in uplevel table
233     or NULL if there is no entry.
234  */
235 LLUplevel *llmp_has_uplevel(int uplevel_sptr);
236 
237 /**
238    \brief ...
239  */
240 void dump_all_uplevel(void);
241 
242 /**
243    \brief ...
244  */
245 void dump_uplevel(LLUplevel *up);
246 
247 /**
248    \brief ...
249  */
250 void llmp_add_shared_var_charlen(LLUplevel *up, int shared_sptr);
251 
252 /**
253    \brief ...
254  */
255 void llmp_append_uplevel(int from_sptr, int to_sptr);
256 
257 /**
258    \brief ...
259  */
260 void llmp_concur_add_shared_var(int uplevel_sptr, int shared_sptr);
261 
262 /**
263    \brief ...
264  */
265 void llmp_reset_uplevel(void);
266 
267 /**
268    \brief Return symbol pointer of its parent.
269  */
270 SPTR llmp_get_parent_sptr(SPTR);
271 
272 /**
273    \brief Create a task object if it does not already exist for \p scope_sptr
274    Add a private sptr to the task object.  shared, priv: See
275    llmp_task_add_private
276  */
277 void llmp_task_add(int scope_sptr, int shared_sptr, SPTR private_sptr);
278 
279 /**
280    \brief ...
281  */
282 void llmp_task_set_fnsptr(LLTask *task, int task_sptr);
283 
284 /**
285    \brief Set the dtype (actual struct of member pointers)
286  */
287 void llmp_uplevel_set_dtype(LLUplevel *up, DTYPE dtype);
288 
289 /**
290    \brief Set uplevel parent field.
291  */
292 void llmp_uplevel_set_parent(SPTR uplevel_sptr, SPTR parent_sptr);
293 
294 /**
295    \brief Return outermost uplevel of current region.
296  */
297 LLUplevel *llmp_outermost_uplevel(SPTR child);
298 
299 /**
300    \brief Return uplevel pointer of current uplevel's parent
301  */
302 LLUplevel *llmp_parent_uplevel(SPTR child);
303 
304 #endif /* LLMPUTIL_H_ */
305