Daily bump.
[official-gcc.git] / libgomp / config / gcn / target.c
blob0a3008454b74141b3a10e9e1c1974fc9e83233be
1 /* Copyright (C) 2017-2024 Free Software Foundation, Inc.
2 Contributed by Mentor Embedded.
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
7 Libgomp is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgomp.h"
27 #include "libgomp-gcn.h"
28 #include <limits.h>
30 extern volatile struct gomp_offload_icvs GOMP_ADDITIONAL_ICVS;
32 /* Implement OpenMP 'teams' construct.
34 Initialize upon FIRST call. Return whether this invocation is active.
35 Depending on whether NUM_TEAMS_LOWER asks for more teams than are provided
36 in hardware, we may need to loop multiple times; in that case make sure to
37 update the team-level variable used by 'omp_get_team_num', as we then can't
38 just use '__builtin_gcn_dim_pos (0)'. */
40 bool
41 GOMP_teams4 (unsigned int num_teams_lower, unsigned int num_teams_upper,
42 unsigned int thread_limit, bool first)
44 int __lds *gomp_team_num = (int __lds *) GOMP_TEAM_NUM;
45 unsigned int num_workgroups = __builtin_gcn_dim_size (0);
46 if (!first)
48 unsigned int team_num;
49 if (num_workgroups > gomp_num_teams_var)
50 return false;
51 team_num = *gomp_team_num;
52 if (team_num > gomp_num_teams_var - num_workgroups)
53 return false;
54 *gomp_team_num = team_num + num_workgroups;
55 return true;
57 if (thread_limit)
59 struct gomp_task_icv *icv = gomp_icv (true);
60 icv->thread_limit_var
61 = thread_limit > INT_MAX ? UINT_MAX : thread_limit;
63 if (!num_teams_upper)
64 num_teams_upper = ((GOMP_ADDITIONAL_ICVS.nteams > 0
65 && num_workgroups > GOMP_ADDITIONAL_ICVS.nteams)
66 ? GOMP_ADDITIONAL_ICVS.nteams : num_workgroups);
67 else if (num_workgroups < num_teams_lower)
68 num_teams_upper = num_teams_lower;
69 else if (num_workgroups < num_teams_upper)
70 num_teams_upper = num_workgroups;
71 unsigned int workgroup_id = __builtin_gcn_dim_pos (0);
72 if (workgroup_id >= num_teams_upper)
73 return false;
74 *gomp_team_num = workgroup_id;
75 gomp_num_teams_var = num_teams_upper - 1;
76 return true;
79 int
80 omp_pause_resource (omp_pause_resource_t kind, int device_num)
82 (void) kind;
83 (void) device_num;
84 return -1;
87 int
88 omp_pause_resource_all (omp_pause_resource_t kind)
90 (void) kind;
91 return -1;
94 ialias (omp_pause_resource)
95 ialias (omp_pause_resource_all)
97 void
98 GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
99 void **hostaddrs, size_t *sizes, unsigned short *kinds,
100 unsigned int flags, void **depend, void **args)
102 (void) flags;
103 (void) depend;
104 (void) args;
106 if (device != GOMP_DEVICE_HOST_FALLBACK || fn == NULL)
107 return;
109 /* The output data is at ((void*) kernargs)[2]. */
110 register void **kernargs = (void**) __builtin_gcn_kernarg_ptr ();
111 struct output *data = (struct output *) kernargs[2];
112 /* Reserve one slot. */
113 unsigned int index = __atomic_fetch_add (&data->next_output, 1,
114 __ATOMIC_ACQUIRE);
116 if ((unsigned int) (index + 1) < data->consumed)
117 abort (); /* Overflow. */
119 /* Spinlock while the host catches up. */
120 if (index >= 1024)
121 while (__atomic_load_n (&data->consumed, __ATOMIC_ACQUIRE)
122 <= (index - 1024))
123 asm ("s_sleep 64");
125 unsigned int slot = index % 1024;
126 data->queue[slot].value_u64[0] = (uint64_t) fn;
127 data->queue[slot].value_u64[1] = (uint64_t) mapnum;
128 data->queue[slot].value_u64[2] = (uint64_t) hostaddrs;
129 data->queue[slot].value_u64[3] = (uint64_t) sizes;
130 data->queue[slot].value_u64[4] = (uint64_t) kinds;
131 data->queue[slot].value_u64[5] = (uint64_t) GOMP_ADDITIONAL_ICVS.device_num;
133 data->queue[slot].type = 4; /* Reverse offload. */
134 __atomic_store_n (&data->queue[slot].written, 1, __ATOMIC_RELEASE);
136 /* Spinlock while the host catches up. */
137 while (__atomic_load_n (&data->queue[slot].written, __ATOMIC_ACQUIRE) != 0)
138 asm ("s_sleep 64");
141 void
142 GOMP_target_data_ext (int device, size_t mapnum, void **hostaddrs,
143 size_t *sizes, unsigned short *kinds)
145 (void) device;
146 (void) mapnum;
147 (void) hostaddrs;
148 (void) sizes;
149 (void) kinds;
150 __builtin_unreachable ();
153 void
154 GOMP_target_end_data (void)
156 __builtin_unreachable ();
159 void
160 GOMP_target_update_ext (int device, size_t mapnum, void **hostaddrs,
161 size_t *sizes, unsigned short *kinds,
162 unsigned int flags, void **depend)
164 (void) device;
165 (void) mapnum;
166 (void) hostaddrs;
167 (void) sizes;
168 (void) kinds;
169 (void) flags;
170 (void) depend;
171 __builtin_unreachable ();
174 void
175 GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
176 size_t *sizes, unsigned short *kinds,
177 unsigned int flags, void **depend)
179 (void) device;
180 (void) mapnum;
181 (void) hostaddrs;
182 (void) sizes;
183 (void) kinds;
184 (void) flags;
185 (void) depend;
186 __builtin_unreachable ();
190 omp_get_num_interop_properties (const omp_interop_t interop
191 __attribute__ ((unused)))
193 return 0;
196 omp_intptr_t
197 omp_get_interop_int (const omp_interop_t interop,
198 omp_interop_property_t property_id,
199 omp_interop_rc_t *ret_code)
201 if (ret_code == NULL)
202 return 0;
203 if (property_id < omp_ipr_first || property_id >= 0)
204 *ret_code = omp_irc_out_of_range;
205 else if (interop == omp_interop_none)
206 *ret_code = omp_irc_empty;
207 else
208 *ret_code = omp_irc_other;
209 return 0;
212 void *
213 omp_get_interop_ptr (const omp_interop_t interop,
214 omp_interop_property_t property_id,
215 omp_interop_rc_t *ret_code)
217 if (ret_code == NULL)
218 return NULL;
219 if (property_id < omp_ipr_first || property_id >= 0)
220 *ret_code = omp_irc_out_of_range;
221 else if (interop == omp_interop_none)
222 *ret_code = omp_irc_empty;
223 else
224 *ret_code = omp_irc_other;
225 return NULL;
228 const char *
229 omp_get_interop_str (const omp_interop_t interop,
230 omp_interop_property_t property_id,
231 omp_interop_rc_t *ret_code)
233 if (ret_code == NULL)
234 return NULL;
235 if (property_id < omp_ipr_first || property_id >= 0)
236 *ret_code = omp_irc_out_of_range;
237 else if (interop == omp_interop_none)
238 *ret_code = omp_irc_empty;
239 else
240 *ret_code = omp_irc_other;
241 return NULL;
244 const char *
245 omp_get_interop_name (const omp_interop_t interop __attribute__ ((unused)),
246 omp_interop_property_t property_id)
248 static const char *prop_string[0 - omp_ipr_first]
249 = {"fr_id", "fr_name", "vendor", "vendor_name", "device_num", "platform",
250 "device", "device_context", "targetsync"};
251 if (property_id < omp_ipr_first || property_id >= 0)
252 return NULL;
253 return prop_string[omp_ipr_fr_id - property_id];
256 const char *
257 omp_get_interop_type_desc (const omp_interop_t interop __attribute__ ((unused)),
258 omp_interop_property_t property_id
259 __attribute__ ((unused)))
261 return NULL;
264 const char *
265 omp_get_interop_rc_desc (const omp_interop_t interop __attribute__ ((unused)),
266 omp_interop_rc_t ret_code)
268 static const char *rc_strings[omp_irc_no_value - omp_irc_other + 1]
269 = {"no meaningful value available",
270 "successful",
271 "provided interoperability object is equal to omp_interop_none",
272 "property ID is out of range",
273 "property type is integer; use omp_get_interop_int",
274 "property type is pointer; use omp_get_interop_ptr",
275 "property type is string; use omp_get_interop_str",
276 "obtaining properties is only supported on the initial device"};
277 /* omp_irc_other is returned by device-side omp_get_interop_{int,ptr,str};
278 the host returns for omp_irc_other NULL as it is not used. Besides the
279 three omp_interop_rc_t values used on the device side, handle host values
280 leaked to the device side. */
281 if (ret_code > omp_irc_no_value || ret_code < omp_irc_other)
282 return NULL;
283 return rc_strings[omp_irc_no_value - ret_code];
286 const char *
287 omp_get_uid_from_device (int device_num __attribute__ ((unused)))
289 return NULL;
293 omp_get_device_from_uid (const char *uid __attribute__ ((unused)))
295 return omp_invalid_device;
298 ialias (omp_get_num_interop_properties)
299 ialias (omp_get_interop_int)
300 ialias (omp_get_interop_ptr)
301 ialias (omp_get_interop_str)
302 ialias (omp_get_interop_name)
303 ialias (omp_get_interop_type_desc)
304 ialias (omp_get_interop_rc_desc)
305 ialias (omp_get_uid_from_device)
306 ialias (omp_get_device_from_uid)