xref: /netbsd-src/external/gpl3/gcc.old/dist/libgomp/loop_ull.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1*8feb0f0bSmrg /* Copyright (C) 2005-2020 Free Software Foundation, Inc.
21debfc3dSmrg    Contributed by Richard Henderson <rth@redhat.com>.
31debfc3dSmrg 
41debfc3dSmrg    This file is part of the GNU Offloading and Multi Processing Library
51debfc3dSmrg    (libgomp).
61debfc3dSmrg 
71debfc3dSmrg    Libgomp is free software; you can redistribute it and/or modify it
81debfc3dSmrg    under the terms of the GNU General Public License as published by
91debfc3dSmrg    the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg    any later version.
111debfc3dSmrg 
121debfc3dSmrg    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
141debfc3dSmrg    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
151debfc3dSmrg    more details.
161debfc3dSmrg 
171debfc3dSmrg    Under Section 7 of GPL version 3, you are granted additional
181debfc3dSmrg    permissions described in the GCC Runtime Library Exception, version
191debfc3dSmrg    3.1, as published by the Free Software Foundation.
201debfc3dSmrg 
211debfc3dSmrg    You should have received a copy of the GNU General Public License and
221debfc3dSmrg    a copy of the GCC Runtime Library Exception along with this program;
231debfc3dSmrg    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
241debfc3dSmrg    <http://www.gnu.org/licenses/>.  */
251debfc3dSmrg 
261debfc3dSmrg /* This file handles the LOOP (FOR/DO) construct.  */
271debfc3dSmrg 
281debfc3dSmrg #include <limits.h>
291debfc3dSmrg #include <stdlib.h>
30c0a68be4Smrg #include <string.h>
311debfc3dSmrg #include "libgomp.h"
321debfc3dSmrg 
33c0a68be4Smrg ialias (GOMP_loop_ull_runtime_next)
34c0a68be4Smrg ialias_redirect (GOMP_taskgroup_reduction_register)
35c0a68be4Smrg 
361debfc3dSmrg typedef unsigned long long gomp_ull;
371debfc3dSmrg 
381debfc3dSmrg /* Initialize the given work share construct from the given arguments.  */
391debfc3dSmrg 
401debfc3dSmrg static inline void
gomp_loop_ull_init(struct gomp_work_share * ws,bool up,gomp_ull start,gomp_ull end,gomp_ull incr,enum gomp_schedule_type sched,gomp_ull chunk_size)411debfc3dSmrg gomp_loop_ull_init (struct gomp_work_share *ws, bool up, gomp_ull start,
421debfc3dSmrg 		    gomp_ull end, gomp_ull incr, enum gomp_schedule_type sched,
431debfc3dSmrg 		    gomp_ull chunk_size)
441debfc3dSmrg {
451debfc3dSmrg   ws->sched = sched;
461debfc3dSmrg   ws->chunk_size_ull = chunk_size;
471debfc3dSmrg   /* Canonicalize loops that have zero iterations to ->next == ->end.  */
481debfc3dSmrg   ws->end_ull = ((up && start > end) || (!up && start < end))
491debfc3dSmrg 		? start : end;
501debfc3dSmrg   ws->incr_ull = incr;
511debfc3dSmrg   ws->next_ull = start;
521debfc3dSmrg   ws->mode = 0;
531debfc3dSmrg   if (sched == GFS_DYNAMIC)
541debfc3dSmrg     {
551debfc3dSmrg       ws->chunk_size_ull *= incr;
561debfc3dSmrg 
571debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
581debfc3dSmrg       {
591debfc3dSmrg 	/* For dynamic scheduling prepare things to make each iteration
601debfc3dSmrg 	   faster.  */
611debfc3dSmrg 	struct gomp_thread *thr = gomp_thread ();
621debfc3dSmrg 	struct gomp_team *team = thr->ts.team;
631debfc3dSmrg 	long nthreads = team ? team->nthreads : 1;
641debfc3dSmrg 
651debfc3dSmrg 	if (__builtin_expect (up, 1))
661debfc3dSmrg 	  {
671debfc3dSmrg 	    /* Cheap overflow protection.  */
681debfc3dSmrg 	    if (__builtin_expect ((nthreads | ws->chunk_size_ull)
691debfc3dSmrg 				  < 1ULL << (sizeof (gomp_ull)
701debfc3dSmrg 					     * __CHAR_BIT__ / 2 - 1), 1))
711debfc3dSmrg 	      ws->mode = ws->end_ull < (__LONG_LONG_MAX__ * 2ULL + 1
721debfc3dSmrg 					- (nthreads + 1) * ws->chunk_size_ull);
731debfc3dSmrg 	  }
741debfc3dSmrg 	/* Cheap overflow protection.  */
751debfc3dSmrg 	else if (__builtin_expect ((nthreads | -ws->chunk_size_ull)
761debfc3dSmrg 				   < 1ULL << (sizeof (gomp_ull)
771debfc3dSmrg 					      * __CHAR_BIT__ / 2 - 1), 1))
781debfc3dSmrg 	  ws->mode = ws->end_ull > ((nthreads + 1) * -ws->chunk_size_ull
791debfc3dSmrg 				    - (__LONG_LONG_MAX__ * 2ULL + 1));
801debfc3dSmrg       }
811debfc3dSmrg #endif
821debfc3dSmrg     }
831debfc3dSmrg   if (!up)
841debfc3dSmrg     ws->mode |= 2;
851debfc3dSmrg }
861debfc3dSmrg 
871debfc3dSmrg /* The *_start routines are called when first encountering a loop construct
881debfc3dSmrg    that is not bound directly to a parallel construct.  The first thread
891debfc3dSmrg    that arrives will create the work-share construct; subsequent threads
901debfc3dSmrg    will see the construct exists and allocate work from it.
911debfc3dSmrg 
921debfc3dSmrg    START, END, INCR are the bounds of the loop; due to the restrictions of
931debfc3dSmrg    OpenMP, these values must be the same in every thread.  This is not
941debfc3dSmrg    verified (nor is it entirely verifiable, since START is not necessarily
951debfc3dSmrg    retained intact in the work-share data structure).  CHUNK_SIZE is the
961debfc3dSmrg    scheduling parameter; again this must be identical in all threads.
971debfc3dSmrg 
981debfc3dSmrg    Returns true if there's any work for this thread to perform.  If so,
991debfc3dSmrg    *ISTART and *IEND are filled with the bounds of the iteration block
1001debfc3dSmrg    allocated to this thread.  Returns false if all work was assigned to
1011debfc3dSmrg    other threads prior to this thread's arrival.  */
1021debfc3dSmrg 
1031debfc3dSmrg static bool
gomp_loop_ull_static_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)1041debfc3dSmrg gomp_loop_ull_static_start (bool up, gomp_ull start, gomp_ull end,
1051debfc3dSmrg 			    gomp_ull incr, gomp_ull chunk_size,
1061debfc3dSmrg 			    gomp_ull *istart, gomp_ull *iend)
1071debfc3dSmrg {
1081debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
1091debfc3dSmrg 
1101debfc3dSmrg   thr->ts.static_trip = 0;
111c0a68be4Smrg   if (gomp_work_share_start (0))
1121debfc3dSmrg     {
1131debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
1141debfc3dSmrg 			  GFS_STATIC, chunk_size);
1151debfc3dSmrg       gomp_work_share_init_done ();
1161debfc3dSmrg     }
1171debfc3dSmrg 
1181debfc3dSmrg   return !gomp_iter_ull_static_next (istart, iend);
1191debfc3dSmrg }
1201debfc3dSmrg 
1211debfc3dSmrg static bool
gomp_loop_ull_dynamic_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)1221debfc3dSmrg gomp_loop_ull_dynamic_start (bool up, gomp_ull start, gomp_ull end,
1231debfc3dSmrg 			     gomp_ull incr, gomp_ull chunk_size,
1241debfc3dSmrg 			     gomp_ull *istart, gomp_ull *iend)
1251debfc3dSmrg {
1261debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
1271debfc3dSmrg   bool ret;
1281debfc3dSmrg 
129c0a68be4Smrg   if (gomp_work_share_start (0))
1301debfc3dSmrg     {
1311debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
1321debfc3dSmrg 			  GFS_DYNAMIC, chunk_size);
1331debfc3dSmrg       gomp_work_share_init_done ();
1341debfc3dSmrg     }
1351debfc3dSmrg 
1361debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
1371debfc3dSmrg   ret = gomp_iter_ull_dynamic_next (istart, iend);
1381debfc3dSmrg #else
1391debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
1401debfc3dSmrg   ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
1411debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
1421debfc3dSmrg #endif
1431debfc3dSmrg 
1441debfc3dSmrg   return ret;
1451debfc3dSmrg }
1461debfc3dSmrg 
1471debfc3dSmrg static bool
gomp_loop_ull_guided_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)1481debfc3dSmrg gomp_loop_ull_guided_start (bool up, gomp_ull start, gomp_ull end,
1491debfc3dSmrg 			    gomp_ull incr, gomp_ull chunk_size,
1501debfc3dSmrg 			    gomp_ull *istart, gomp_ull *iend)
1511debfc3dSmrg {
1521debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
1531debfc3dSmrg   bool ret;
1541debfc3dSmrg 
155c0a68be4Smrg   if (gomp_work_share_start (0))
1561debfc3dSmrg     {
1571debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
1581debfc3dSmrg 			  GFS_GUIDED, chunk_size);
1591debfc3dSmrg       gomp_work_share_init_done ();
1601debfc3dSmrg     }
1611debfc3dSmrg 
1621debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
1631debfc3dSmrg   ret = gomp_iter_ull_guided_next (istart, iend);
1641debfc3dSmrg #else
1651debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
1661debfc3dSmrg   ret = gomp_iter_ull_guided_next_locked (istart, iend);
1671debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
1681debfc3dSmrg #endif
1691debfc3dSmrg 
1701debfc3dSmrg   return ret;
1711debfc3dSmrg }
1721debfc3dSmrg 
1731debfc3dSmrg bool
GOMP_loop_ull_runtime_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull * istart,gomp_ull * iend)1741debfc3dSmrg GOMP_loop_ull_runtime_start (bool up, gomp_ull start, gomp_ull end,
1751debfc3dSmrg 			     gomp_ull incr, gomp_ull *istart, gomp_ull *iend)
1761debfc3dSmrg {
1771debfc3dSmrg   struct gomp_task_icv *icv = gomp_icv (false);
178c0a68be4Smrg   switch (icv->run_sched_var & ~GFS_MONOTONIC)
1791debfc3dSmrg     {
1801debfc3dSmrg     case GFS_STATIC:
1811debfc3dSmrg       return gomp_loop_ull_static_start (up, start, end, incr,
1821debfc3dSmrg 					 icv->run_sched_chunk_size,
1831debfc3dSmrg 					 istart, iend);
1841debfc3dSmrg     case GFS_DYNAMIC:
1851debfc3dSmrg       return gomp_loop_ull_dynamic_start (up, start, end, incr,
1861debfc3dSmrg 					  icv->run_sched_chunk_size,
1871debfc3dSmrg 					  istart, iend);
1881debfc3dSmrg     case GFS_GUIDED:
1891debfc3dSmrg       return gomp_loop_ull_guided_start (up, start, end, incr,
1901debfc3dSmrg 					 icv->run_sched_chunk_size,
1911debfc3dSmrg 					 istart, iend);
1921debfc3dSmrg     case GFS_AUTO:
1931debfc3dSmrg       /* For now map to schedule(static), later on we could play with feedback
1941debfc3dSmrg 	 driven choice.  */
1951debfc3dSmrg       return gomp_loop_ull_static_start (up, start, end, incr,
1961debfc3dSmrg 					 0, istart, iend);
1971debfc3dSmrg     default:
1981debfc3dSmrg       abort ();
1991debfc3dSmrg     }
2001debfc3dSmrg }
2011debfc3dSmrg 
202c0a68be4Smrg static long
gomp_adjust_sched(long sched,gomp_ull * chunk_size)203c0a68be4Smrg gomp_adjust_sched (long sched, gomp_ull *chunk_size)
204c0a68be4Smrg {
205c0a68be4Smrg   sched &= ~GFS_MONOTONIC;
206c0a68be4Smrg   switch (sched)
207c0a68be4Smrg     {
208c0a68be4Smrg     case GFS_STATIC:
209c0a68be4Smrg     case GFS_DYNAMIC:
210c0a68be4Smrg     case GFS_GUIDED:
211c0a68be4Smrg       return sched;
212c0a68be4Smrg     /* GFS_RUNTIME is used for runtime schedule without monotonic
213c0a68be4Smrg        or nonmonotonic modifiers on the clause.
214c0a68be4Smrg        GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic
215c0a68be4Smrg        modifier.  */
216c0a68be4Smrg     case GFS_RUNTIME:
217c0a68be4Smrg     /* GFS_AUTO is used for runtime schedule with nonmonotonic
218c0a68be4Smrg        modifier.  */
219c0a68be4Smrg     case GFS_AUTO:
220c0a68be4Smrg       {
221c0a68be4Smrg 	struct gomp_task_icv *icv = gomp_icv (false);
222c0a68be4Smrg 	sched = icv->run_sched_var & ~GFS_MONOTONIC;
223c0a68be4Smrg 	switch (sched)
224c0a68be4Smrg 	  {
225c0a68be4Smrg 	  case GFS_STATIC:
226c0a68be4Smrg 	  case GFS_DYNAMIC:
227c0a68be4Smrg 	  case GFS_GUIDED:
228c0a68be4Smrg 	    *chunk_size = icv->run_sched_chunk_size;
229c0a68be4Smrg 	    break;
230c0a68be4Smrg 	  case GFS_AUTO:
231c0a68be4Smrg 	    sched = GFS_STATIC;
232c0a68be4Smrg 	    *chunk_size = 0;
233c0a68be4Smrg 	    break;
234c0a68be4Smrg 	  default:
235c0a68be4Smrg 	    abort ();
236c0a68be4Smrg 	  }
237c0a68be4Smrg 	return sched;
238c0a68be4Smrg       }
239c0a68be4Smrg     default:
240c0a68be4Smrg       abort ();
241c0a68be4Smrg     }
242c0a68be4Smrg }
243c0a68be4Smrg 
244c0a68be4Smrg bool
GOMP_loop_ull_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,long sched,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend,uintptr_t * reductions,void ** mem)245c0a68be4Smrg GOMP_loop_ull_start (bool up, gomp_ull start, gomp_ull end,
246c0a68be4Smrg 		     gomp_ull incr, long sched, gomp_ull chunk_size,
247c0a68be4Smrg 		     gomp_ull *istart, gomp_ull *iend,
248c0a68be4Smrg 		     uintptr_t *reductions, void **mem)
249c0a68be4Smrg {
250c0a68be4Smrg   struct gomp_thread *thr = gomp_thread ();
251c0a68be4Smrg 
252c0a68be4Smrg   thr->ts.static_trip = 0;
253c0a68be4Smrg   if (reductions)
254c0a68be4Smrg     gomp_workshare_taskgroup_start ();
255c0a68be4Smrg   if (gomp_work_share_start (0))
256c0a68be4Smrg     {
257c0a68be4Smrg       sched = gomp_adjust_sched (sched, &chunk_size);
258c0a68be4Smrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
259c0a68be4Smrg       			  sched, chunk_size);
260c0a68be4Smrg       if (reductions)
261c0a68be4Smrg 	{
262c0a68be4Smrg 	  GOMP_taskgroup_reduction_register (reductions);
263c0a68be4Smrg 	  thr->task->taskgroup->workshare = true;
264c0a68be4Smrg 	  thr->ts.work_share->task_reductions = reductions;
265c0a68be4Smrg 	}
266c0a68be4Smrg       if (mem)
267c0a68be4Smrg 	{
268c0a68be4Smrg 	  uintptr_t size = (uintptr_t) *mem;
269c0a68be4Smrg #define INLINE_ORDERED_TEAM_IDS_OFF \
270c0a68be4Smrg   ((offsetof (struct gomp_work_share, inline_ordered_team_ids)		\
271c0a68be4Smrg     + __alignof__ (long long) - 1) & ~(__alignof__ (long long) - 1))
272c0a68be4Smrg 	  if (size > (sizeof (struct gomp_work_share)
273c0a68be4Smrg 		      - INLINE_ORDERED_TEAM_IDS_OFF))
274c0a68be4Smrg 	    *mem
275c0a68be4Smrg 	      = (void *) (thr->ts.work_share->ordered_team_ids
276c0a68be4Smrg 			  = gomp_malloc_cleared (size));
277c0a68be4Smrg 	  else
278c0a68be4Smrg 	    *mem = memset (((char *) thr->ts.work_share)
279c0a68be4Smrg 			   + INLINE_ORDERED_TEAM_IDS_OFF, '\0', size);
280c0a68be4Smrg 	}
281c0a68be4Smrg       gomp_work_share_init_done ();
282c0a68be4Smrg     }
283c0a68be4Smrg   else
284c0a68be4Smrg     {
285c0a68be4Smrg       if (reductions)
286c0a68be4Smrg 	{
287c0a68be4Smrg 	  uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
288c0a68be4Smrg 	  gomp_workshare_task_reduction_register (reductions,
289c0a68be4Smrg 						  first_reductions);
290c0a68be4Smrg 	}
291c0a68be4Smrg       if (mem)
292c0a68be4Smrg 	{
293c0a68be4Smrg 	  if ((offsetof (struct gomp_work_share, inline_ordered_team_ids)
294c0a68be4Smrg 	       & (__alignof__ (long long) - 1)) == 0)
295c0a68be4Smrg 	    *mem = (void *) thr->ts.work_share->ordered_team_ids;
296c0a68be4Smrg 	  else
297c0a68be4Smrg 	    {
298c0a68be4Smrg 	      uintptr_t p = (uintptr_t) thr->ts.work_share->ordered_team_ids;
299c0a68be4Smrg 	      p += __alignof__ (long long) - 1;
300c0a68be4Smrg 	      p &= ~(__alignof__ (long long) - 1);
301c0a68be4Smrg 	      *mem = (void *) p;
302c0a68be4Smrg 	    }
303c0a68be4Smrg 	}
304c0a68be4Smrg     }
305c0a68be4Smrg 
306c0a68be4Smrg   return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend);
307c0a68be4Smrg }
308c0a68be4Smrg 
3091debfc3dSmrg /* The *_ordered_*_start routines are similar.  The only difference is that
3101debfc3dSmrg    this work-share construct is initialized to expect an ORDERED section.  */
3111debfc3dSmrg 
3121debfc3dSmrg static bool
gomp_loop_ull_ordered_static_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)3131debfc3dSmrg gomp_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end,
3141debfc3dSmrg 				    gomp_ull incr, gomp_ull chunk_size,
3151debfc3dSmrg 				    gomp_ull *istart, gomp_ull *iend)
3161debfc3dSmrg {
3171debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
3181debfc3dSmrg 
3191debfc3dSmrg   thr->ts.static_trip = 0;
320c0a68be4Smrg   if (gomp_work_share_start (1))
3211debfc3dSmrg     {
3221debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
3231debfc3dSmrg 			  GFS_STATIC, chunk_size);
3241debfc3dSmrg       gomp_ordered_static_init ();
3251debfc3dSmrg       gomp_work_share_init_done ();
3261debfc3dSmrg     }
3271debfc3dSmrg 
3281debfc3dSmrg   return !gomp_iter_ull_static_next (istart, iend);
3291debfc3dSmrg }
3301debfc3dSmrg 
3311debfc3dSmrg static bool
gomp_loop_ull_ordered_dynamic_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)3321debfc3dSmrg gomp_loop_ull_ordered_dynamic_start (bool up, gomp_ull start, gomp_ull end,
3331debfc3dSmrg 				     gomp_ull incr, gomp_ull chunk_size,
3341debfc3dSmrg 				     gomp_ull *istart, gomp_ull *iend)
3351debfc3dSmrg {
3361debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
3371debfc3dSmrg   bool ret;
3381debfc3dSmrg 
339c0a68be4Smrg   if (gomp_work_share_start (1))
3401debfc3dSmrg     {
3411debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
3421debfc3dSmrg 			  GFS_DYNAMIC, chunk_size);
3431debfc3dSmrg       gomp_mutex_lock (&thr->ts.work_share->lock);
3441debfc3dSmrg       gomp_work_share_init_done ();
3451debfc3dSmrg     }
3461debfc3dSmrg   else
3471debfc3dSmrg     gomp_mutex_lock (&thr->ts.work_share->lock);
3481debfc3dSmrg 
3491debfc3dSmrg   ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
3501debfc3dSmrg   if (ret)
3511debfc3dSmrg     gomp_ordered_first ();
3521debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
3531debfc3dSmrg 
3541debfc3dSmrg   return ret;
3551debfc3dSmrg }
3561debfc3dSmrg 
3571debfc3dSmrg static bool
gomp_loop_ull_ordered_guided_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)3581debfc3dSmrg gomp_loop_ull_ordered_guided_start (bool up, gomp_ull start, gomp_ull end,
3591debfc3dSmrg 				    gomp_ull incr, gomp_ull chunk_size,
3601debfc3dSmrg 				    gomp_ull *istart, gomp_ull *iend)
3611debfc3dSmrg {
3621debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
3631debfc3dSmrg   bool ret;
3641debfc3dSmrg 
365c0a68be4Smrg   if (gomp_work_share_start (1))
3661debfc3dSmrg     {
3671debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
3681debfc3dSmrg 			  GFS_GUIDED, chunk_size);
3691debfc3dSmrg       gomp_mutex_lock (&thr->ts.work_share->lock);
3701debfc3dSmrg       gomp_work_share_init_done ();
3711debfc3dSmrg     }
3721debfc3dSmrg   else
3731debfc3dSmrg     gomp_mutex_lock (&thr->ts.work_share->lock);
3741debfc3dSmrg 
3751debfc3dSmrg   ret = gomp_iter_ull_guided_next_locked (istart, iend);
3761debfc3dSmrg   if (ret)
3771debfc3dSmrg     gomp_ordered_first ();
3781debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
3791debfc3dSmrg 
3801debfc3dSmrg   return ret;
3811debfc3dSmrg }
3821debfc3dSmrg 
3831debfc3dSmrg bool
GOMP_loop_ull_ordered_runtime_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull * istart,gomp_ull * iend)3841debfc3dSmrg GOMP_loop_ull_ordered_runtime_start (bool up, gomp_ull start, gomp_ull end,
3851debfc3dSmrg 				     gomp_ull incr, gomp_ull *istart,
3861debfc3dSmrg 				     gomp_ull *iend)
3871debfc3dSmrg {
3881debfc3dSmrg   struct gomp_task_icv *icv = gomp_icv (false);
389c0a68be4Smrg   switch (icv->run_sched_var & ~GFS_MONOTONIC)
3901debfc3dSmrg     {
3911debfc3dSmrg     case GFS_STATIC:
3921debfc3dSmrg       return gomp_loop_ull_ordered_static_start (up, start, end, incr,
3931debfc3dSmrg 						 icv->run_sched_chunk_size,
3941debfc3dSmrg 						 istart, iend);
3951debfc3dSmrg     case GFS_DYNAMIC:
3961debfc3dSmrg       return gomp_loop_ull_ordered_dynamic_start (up, start, end, incr,
3971debfc3dSmrg 						  icv->run_sched_chunk_size,
3981debfc3dSmrg 						  istart, iend);
3991debfc3dSmrg     case GFS_GUIDED:
4001debfc3dSmrg       return gomp_loop_ull_ordered_guided_start (up, start, end, incr,
4011debfc3dSmrg 						 icv->run_sched_chunk_size,
4021debfc3dSmrg 						 istart, iend);
4031debfc3dSmrg     case GFS_AUTO:
4041debfc3dSmrg       /* For now map to schedule(static), later on we could play with feedback
4051debfc3dSmrg 	 driven choice.  */
4061debfc3dSmrg       return gomp_loop_ull_ordered_static_start (up, start, end, incr,
4071debfc3dSmrg 						 0, istart, iend);
4081debfc3dSmrg     default:
4091debfc3dSmrg       abort ();
4101debfc3dSmrg     }
4111debfc3dSmrg }
4121debfc3dSmrg 
413c0a68be4Smrg bool
GOMP_loop_ull_ordered_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,long sched,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend,uintptr_t * reductions,void ** mem)414c0a68be4Smrg GOMP_loop_ull_ordered_start (bool up, gomp_ull start, gomp_ull end,
415c0a68be4Smrg 			     gomp_ull incr, long sched, gomp_ull chunk_size,
416c0a68be4Smrg 			     gomp_ull *istart, gomp_ull *iend,
417c0a68be4Smrg 			     uintptr_t *reductions, void **mem)
418c0a68be4Smrg {
419c0a68be4Smrg   struct gomp_thread *thr = gomp_thread ();
420c0a68be4Smrg   size_t ordered = 1;
421c0a68be4Smrg   bool ret;
422c0a68be4Smrg 
423c0a68be4Smrg   thr->ts.static_trip = 0;
424c0a68be4Smrg   if (reductions)
425c0a68be4Smrg     gomp_workshare_taskgroup_start ();
426c0a68be4Smrg   if (mem)
427c0a68be4Smrg     ordered += (uintptr_t) *mem;
428c0a68be4Smrg   if (gomp_work_share_start (ordered))
429c0a68be4Smrg     {
430c0a68be4Smrg       sched = gomp_adjust_sched (sched, &chunk_size);
431c0a68be4Smrg       gomp_loop_ull_init (thr->ts.work_share, up, start, end, incr,
432c0a68be4Smrg 			  sched, chunk_size);
433c0a68be4Smrg       if (reductions)
434c0a68be4Smrg 	{
435c0a68be4Smrg 	  GOMP_taskgroup_reduction_register (reductions);
436c0a68be4Smrg 	  thr->task->taskgroup->workshare = true;
437c0a68be4Smrg 	  thr->ts.work_share->task_reductions = reductions;
438c0a68be4Smrg 	}
439c0a68be4Smrg       if (sched == GFS_STATIC)
440c0a68be4Smrg 	gomp_ordered_static_init ();
441c0a68be4Smrg       else
442c0a68be4Smrg 	gomp_mutex_lock (&thr->ts.work_share->lock);
443c0a68be4Smrg       gomp_work_share_init_done ();
444c0a68be4Smrg     }
445c0a68be4Smrg   else
446c0a68be4Smrg     {
447c0a68be4Smrg       if (reductions)
448c0a68be4Smrg 	{
449c0a68be4Smrg 	  uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
450c0a68be4Smrg 	  gomp_workshare_task_reduction_register (reductions,
451c0a68be4Smrg 						  first_reductions);
452c0a68be4Smrg 	}
453c0a68be4Smrg       sched = thr->ts.work_share->sched;
454c0a68be4Smrg       if (sched != GFS_STATIC)
455c0a68be4Smrg 	gomp_mutex_lock (&thr->ts.work_share->lock);
456c0a68be4Smrg     }
457c0a68be4Smrg 
458c0a68be4Smrg   if (mem)
459c0a68be4Smrg     {
460c0a68be4Smrg       uintptr_t p
461c0a68be4Smrg 	= (uintptr_t) (thr->ts.work_share->ordered_team_ids
462c0a68be4Smrg 		       + (thr->ts.team ? thr->ts.team->nthreads : 1));
463c0a68be4Smrg       p += __alignof__ (long long) - 1;
464c0a68be4Smrg       p &= ~(__alignof__ (long long) - 1);
465c0a68be4Smrg       *mem = (void *) p;
466c0a68be4Smrg     }
467c0a68be4Smrg 
468c0a68be4Smrg   switch (sched)
469c0a68be4Smrg     {
470c0a68be4Smrg     case GFS_STATIC:
471c0a68be4Smrg     case GFS_AUTO:
472c0a68be4Smrg       return !gomp_iter_ull_static_next (istart, iend);
473c0a68be4Smrg     case GFS_DYNAMIC:
474c0a68be4Smrg       ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
475c0a68be4Smrg       break;
476c0a68be4Smrg     case GFS_GUIDED:
477c0a68be4Smrg       ret = gomp_iter_ull_guided_next_locked (istart, iend);
478c0a68be4Smrg       break;
479c0a68be4Smrg     default:
480c0a68be4Smrg       abort ();
481c0a68be4Smrg     }
482c0a68be4Smrg 
483c0a68be4Smrg   if (ret)
484c0a68be4Smrg     gomp_ordered_first ();
485c0a68be4Smrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
486c0a68be4Smrg   return ret;
487c0a68be4Smrg }
488c0a68be4Smrg 
4891debfc3dSmrg /* The *_doacross_*_start routines are similar.  The only difference is that
4901debfc3dSmrg    this work-share construct is initialized to expect an ORDERED(N) - DOACROSS
4911debfc3dSmrg    section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1
4921debfc3dSmrg    and other COUNTS array elements tell the library number of iterations
4931debfc3dSmrg    in the ordered inner loops.  */
4941debfc3dSmrg 
4951debfc3dSmrg static bool
gomp_loop_ull_doacross_static_start(unsigned ncounts,gomp_ull * counts,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)4961debfc3dSmrg gomp_loop_ull_doacross_static_start (unsigned ncounts, gomp_ull *counts,
4971debfc3dSmrg 				     gomp_ull chunk_size, gomp_ull *istart,
4981debfc3dSmrg 				     gomp_ull *iend)
4991debfc3dSmrg {
5001debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
5011debfc3dSmrg 
5021debfc3dSmrg   thr->ts.static_trip = 0;
503c0a68be4Smrg   if (gomp_work_share_start (0))
5041debfc3dSmrg     {
5051debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
5061debfc3dSmrg 			  GFS_STATIC, chunk_size);
507c0a68be4Smrg       gomp_doacross_ull_init (ncounts, counts, chunk_size, 0);
5081debfc3dSmrg       gomp_work_share_init_done ();
5091debfc3dSmrg     }
5101debfc3dSmrg 
5111debfc3dSmrg   return !gomp_iter_ull_static_next (istart, iend);
5121debfc3dSmrg }
5131debfc3dSmrg 
5141debfc3dSmrg static bool
gomp_loop_ull_doacross_dynamic_start(unsigned ncounts,gomp_ull * counts,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)5151debfc3dSmrg gomp_loop_ull_doacross_dynamic_start (unsigned ncounts, gomp_ull *counts,
5161debfc3dSmrg 				      gomp_ull chunk_size, gomp_ull *istart,
5171debfc3dSmrg 				      gomp_ull *iend)
5181debfc3dSmrg {
5191debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
5201debfc3dSmrg   bool ret;
5211debfc3dSmrg 
522c0a68be4Smrg   if (gomp_work_share_start (0))
5231debfc3dSmrg     {
5241debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
5251debfc3dSmrg 			  GFS_DYNAMIC, chunk_size);
526c0a68be4Smrg       gomp_doacross_ull_init (ncounts, counts, chunk_size, 0);
5271debfc3dSmrg       gomp_work_share_init_done ();
5281debfc3dSmrg     }
5291debfc3dSmrg 
5301debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
5311debfc3dSmrg   ret = gomp_iter_ull_dynamic_next (istart, iend);
5321debfc3dSmrg #else
5331debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
5341debfc3dSmrg   ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
5351debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
5361debfc3dSmrg #endif
5371debfc3dSmrg 
5381debfc3dSmrg   return ret;
5391debfc3dSmrg }
5401debfc3dSmrg 
5411debfc3dSmrg static bool
gomp_loop_ull_doacross_guided_start(unsigned ncounts,gomp_ull * counts,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)5421debfc3dSmrg gomp_loop_ull_doacross_guided_start (unsigned ncounts, gomp_ull *counts,
5431debfc3dSmrg 				     gomp_ull chunk_size, gomp_ull *istart,
5441debfc3dSmrg 				     gomp_ull *iend)
5451debfc3dSmrg {
5461debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
5471debfc3dSmrg   bool ret;
5481debfc3dSmrg 
549c0a68be4Smrg   if (gomp_work_share_start (0))
5501debfc3dSmrg     {
5511debfc3dSmrg       gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
5521debfc3dSmrg 			  GFS_GUIDED, chunk_size);
553c0a68be4Smrg       gomp_doacross_ull_init (ncounts, counts, chunk_size, 0);
5541debfc3dSmrg       gomp_work_share_init_done ();
5551debfc3dSmrg     }
5561debfc3dSmrg 
5571debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
5581debfc3dSmrg   ret = gomp_iter_ull_guided_next (istart, iend);
5591debfc3dSmrg #else
5601debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
5611debfc3dSmrg   ret = gomp_iter_ull_guided_next_locked (istart, iend);
5621debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
5631debfc3dSmrg #endif
5641debfc3dSmrg 
5651debfc3dSmrg   return ret;
5661debfc3dSmrg }
5671debfc3dSmrg 
5681debfc3dSmrg bool
GOMP_loop_ull_doacross_runtime_start(unsigned ncounts,gomp_ull * counts,gomp_ull * istart,gomp_ull * iend)5691debfc3dSmrg GOMP_loop_ull_doacross_runtime_start (unsigned ncounts, gomp_ull *counts,
5701debfc3dSmrg 				      gomp_ull *istart, gomp_ull *iend)
5711debfc3dSmrg {
5721debfc3dSmrg   struct gomp_task_icv *icv = gomp_icv (false);
573c0a68be4Smrg   switch (icv->run_sched_var & ~GFS_MONOTONIC)
5741debfc3dSmrg     {
5751debfc3dSmrg     case GFS_STATIC:
5761debfc3dSmrg       return gomp_loop_ull_doacross_static_start (ncounts, counts,
5771debfc3dSmrg 						  icv->run_sched_chunk_size,
5781debfc3dSmrg 						  istart, iend);
5791debfc3dSmrg     case GFS_DYNAMIC:
5801debfc3dSmrg       return gomp_loop_ull_doacross_dynamic_start (ncounts, counts,
5811debfc3dSmrg 						   icv->run_sched_chunk_size,
5821debfc3dSmrg 						   istart, iend);
5831debfc3dSmrg     case GFS_GUIDED:
5841debfc3dSmrg       return gomp_loop_ull_doacross_guided_start (ncounts, counts,
5851debfc3dSmrg 						  icv->run_sched_chunk_size,
5861debfc3dSmrg 						  istart, iend);
5871debfc3dSmrg     case GFS_AUTO:
5881debfc3dSmrg       /* For now map to schedule(static), later on we could play with feedback
5891debfc3dSmrg 	 driven choice.  */
5901debfc3dSmrg       return gomp_loop_ull_doacross_static_start (ncounts, counts,
5911debfc3dSmrg 						  0, istart, iend);
5921debfc3dSmrg     default:
5931debfc3dSmrg       abort ();
5941debfc3dSmrg     }
5951debfc3dSmrg }
5961debfc3dSmrg 
597c0a68be4Smrg bool
GOMP_loop_ull_doacross_start(unsigned ncounts,gomp_ull * counts,long sched,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend,uintptr_t * reductions,void ** mem)598c0a68be4Smrg GOMP_loop_ull_doacross_start (unsigned ncounts, gomp_ull *counts,
599c0a68be4Smrg 			      long sched, gomp_ull chunk_size,
600c0a68be4Smrg 			      gomp_ull *istart, gomp_ull *iend,
601c0a68be4Smrg 			      uintptr_t *reductions, void **mem)
602c0a68be4Smrg {
603c0a68be4Smrg   struct gomp_thread *thr = gomp_thread ();
604c0a68be4Smrg 
605c0a68be4Smrg   thr->ts.static_trip = 0;
606c0a68be4Smrg   if (reductions)
607c0a68be4Smrg     gomp_workshare_taskgroup_start ();
608c0a68be4Smrg   if (gomp_work_share_start (0))
609c0a68be4Smrg     {
610c0a68be4Smrg       size_t extra = 0;
611c0a68be4Smrg       if (mem)
612c0a68be4Smrg 	extra = (uintptr_t) *mem;
613c0a68be4Smrg       sched = gomp_adjust_sched (sched, &chunk_size);
614c0a68be4Smrg       gomp_loop_ull_init (thr->ts.work_share, true, 0, counts[0], 1,
615c0a68be4Smrg 			  sched, chunk_size);
616c0a68be4Smrg       gomp_doacross_ull_init (ncounts, counts, chunk_size, extra);
617c0a68be4Smrg       if (reductions)
618c0a68be4Smrg 	{
619c0a68be4Smrg 	  GOMP_taskgroup_reduction_register (reductions);
620c0a68be4Smrg 	  thr->task->taskgroup->workshare = true;
621c0a68be4Smrg 	  thr->ts.work_share->task_reductions = reductions;
622c0a68be4Smrg 	}
623c0a68be4Smrg       gomp_work_share_init_done ();
624c0a68be4Smrg     }
625c0a68be4Smrg   else
626c0a68be4Smrg     {
627c0a68be4Smrg       if (reductions)
628c0a68be4Smrg 	{
629c0a68be4Smrg 	  uintptr_t *first_reductions = thr->ts.work_share->task_reductions;
630c0a68be4Smrg 	  gomp_workshare_task_reduction_register (reductions,
631c0a68be4Smrg 						  first_reductions);
632c0a68be4Smrg 	}
633c0a68be4Smrg       sched = thr->ts.work_share->sched;
634c0a68be4Smrg     }
635c0a68be4Smrg 
636c0a68be4Smrg   if (mem)
637c0a68be4Smrg     *mem = thr->ts.work_share->doacross->extra;
638c0a68be4Smrg 
639c0a68be4Smrg   return ialias_call (GOMP_loop_ull_runtime_next) (istart, iend);
640c0a68be4Smrg }
641c0a68be4Smrg 
6421debfc3dSmrg /* The *_next routines are called when the thread completes processing of
6431debfc3dSmrg    the iteration block currently assigned to it.  If the work-share
6441debfc3dSmrg    construct is bound directly to a parallel construct, then the iteration
6451debfc3dSmrg    bounds may have been set up before the parallel.  In which case, this
6461debfc3dSmrg    may be the first iteration for the thread.
6471debfc3dSmrg 
6481debfc3dSmrg    Returns true if there is work remaining to be performed; *ISTART and
6491debfc3dSmrg    *IEND are filled with a new iteration block.  Returns false if all work
6501debfc3dSmrg    has been assigned.  */
6511debfc3dSmrg 
6521debfc3dSmrg static bool
gomp_loop_ull_static_next(gomp_ull * istart,gomp_ull * iend)6531debfc3dSmrg gomp_loop_ull_static_next (gomp_ull *istart, gomp_ull *iend)
6541debfc3dSmrg {
6551debfc3dSmrg   return !gomp_iter_ull_static_next (istart, iend);
6561debfc3dSmrg }
6571debfc3dSmrg 
6581debfc3dSmrg static bool
gomp_loop_ull_dynamic_next(gomp_ull * istart,gomp_ull * iend)6591debfc3dSmrg gomp_loop_ull_dynamic_next (gomp_ull *istart, gomp_ull *iend)
6601debfc3dSmrg {
6611debfc3dSmrg   bool ret;
6621debfc3dSmrg 
6631debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
6641debfc3dSmrg   ret = gomp_iter_ull_dynamic_next (istart, iend);
6651debfc3dSmrg #else
6661debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
6671debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
6681debfc3dSmrg   ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
6691debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
6701debfc3dSmrg #endif
6711debfc3dSmrg 
6721debfc3dSmrg   return ret;
6731debfc3dSmrg }
6741debfc3dSmrg 
6751debfc3dSmrg static bool
gomp_loop_ull_guided_next(gomp_ull * istart,gomp_ull * iend)6761debfc3dSmrg gomp_loop_ull_guided_next (gomp_ull *istart, gomp_ull *iend)
6771debfc3dSmrg {
6781debfc3dSmrg   bool ret;
6791debfc3dSmrg 
6801debfc3dSmrg #if defined HAVE_SYNC_BUILTINS && defined __LP64__
6811debfc3dSmrg   ret = gomp_iter_ull_guided_next (istart, iend);
6821debfc3dSmrg #else
6831debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
6841debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
6851debfc3dSmrg   ret = gomp_iter_ull_guided_next_locked (istart, iend);
6861debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
6871debfc3dSmrg #endif
6881debfc3dSmrg 
6891debfc3dSmrg   return ret;
6901debfc3dSmrg }
6911debfc3dSmrg 
6921debfc3dSmrg bool
GOMP_loop_ull_runtime_next(gomp_ull * istart,gomp_ull * iend)6931debfc3dSmrg GOMP_loop_ull_runtime_next (gomp_ull *istart, gomp_ull *iend)
6941debfc3dSmrg {
6951debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
6961debfc3dSmrg 
6971debfc3dSmrg   switch (thr->ts.work_share->sched)
6981debfc3dSmrg     {
6991debfc3dSmrg     case GFS_STATIC:
7001debfc3dSmrg     case GFS_AUTO:
7011debfc3dSmrg       return gomp_loop_ull_static_next (istart, iend);
7021debfc3dSmrg     case GFS_DYNAMIC:
7031debfc3dSmrg       return gomp_loop_ull_dynamic_next (istart, iend);
7041debfc3dSmrg     case GFS_GUIDED:
7051debfc3dSmrg       return gomp_loop_ull_guided_next (istart, iend);
7061debfc3dSmrg     default:
7071debfc3dSmrg       abort ();
7081debfc3dSmrg     }
7091debfc3dSmrg }
7101debfc3dSmrg 
7111debfc3dSmrg /* The *_ordered_*_next routines are called when the thread completes
7121debfc3dSmrg    processing of the iteration block currently assigned to it.
7131debfc3dSmrg 
7141debfc3dSmrg    Returns true if there is work remaining to be performed; *ISTART and
7151debfc3dSmrg    *IEND are filled with a new iteration block.  Returns false if all work
7161debfc3dSmrg    has been assigned.  */
7171debfc3dSmrg 
7181debfc3dSmrg static bool
gomp_loop_ull_ordered_static_next(gomp_ull * istart,gomp_ull * iend)7191debfc3dSmrg gomp_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend)
7201debfc3dSmrg {
7211debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
7221debfc3dSmrg   int test;
7231debfc3dSmrg 
7241debfc3dSmrg   gomp_ordered_sync ();
7251debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
7261debfc3dSmrg   test = gomp_iter_ull_static_next (istart, iend);
7271debfc3dSmrg   if (test >= 0)
7281debfc3dSmrg     gomp_ordered_static_next ();
7291debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
7301debfc3dSmrg 
7311debfc3dSmrg   return test == 0;
7321debfc3dSmrg }
7331debfc3dSmrg 
7341debfc3dSmrg static bool
gomp_loop_ull_ordered_dynamic_next(gomp_ull * istart,gomp_ull * iend)7351debfc3dSmrg gomp_loop_ull_ordered_dynamic_next (gomp_ull *istart, gomp_ull *iend)
7361debfc3dSmrg {
7371debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
7381debfc3dSmrg   bool ret;
7391debfc3dSmrg 
7401debfc3dSmrg   gomp_ordered_sync ();
7411debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
7421debfc3dSmrg   ret = gomp_iter_ull_dynamic_next_locked (istart, iend);
7431debfc3dSmrg   if (ret)
7441debfc3dSmrg     gomp_ordered_next ();
7451debfc3dSmrg   else
7461debfc3dSmrg     gomp_ordered_last ();
7471debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
7481debfc3dSmrg 
7491debfc3dSmrg   return ret;
7501debfc3dSmrg }
7511debfc3dSmrg 
7521debfc3dSmrg static bool
gomp_loop_ull_ordered_guided_next(gomp_ull * istart,gomp_ull * iend)7531debfc3dSmrg gomp_loop_ull_ordered_guided_next (gomp_ull *istart, gomp_ull *iend)
7541debfc3dSmrg {
7551debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
7561debfc3dSmrg   bool ret;
7571debfc3dSmrg 
7581debfc3dSmrg   gomp_ordered_sync ();
7591debfc3dSmrg   gomp_mutex_lock (&thr->ts.work_share->lock);
7601debfc3dSmrg   ret = gomp_iter_ull_guided_next_locked (istart, iend);
7611debfc3dSmrg   if (ret)
7621debfc3dSmrg     gomp_ordered_next ();
7631debfc3dSmrg   else
7641debfc3dSmrg     gomp_ordered_last ();
7651debfc3dSmrg   gomp_mutex_unlock (&thr->ts.work_share->lock);
7661debfc3dSmrg 
7671debfc3dSmrg   return ret;
7681debfc3dSmrg }
7691debfc3dSmrg 
7701debfc3dSmrg bool
GOMP_loop_ull_ordered_runtime_next(gomp_ull * istart,gomp_ull * iend)7711debfc3dSmrg GOMP_loop_ull_ordered_runtime_next (gomp_ull *istart, gomp_ull *iend)
7721debfc3dSmrg {
7731debfc3dSmrg   struct gomp_thread *thr = gomp_thread ();
7741debfc3dSmrg 
7751debfc3dSmrg   switch (thr->ts.work_share->sched)
7761debfc3dSmrg     {
7771debfc3dSmrg     case GFS_STATIC:
7781debfc3dSmrg     case GFS_AUTO:
7791debfc3dSmrg       return gomp_loop_ull_ordered_static_next (istart, iend);
7801debfc3dSmrg     case GFS_DYNAMIC:
7811debfc3dSmrg       return gomp_loop_ull_ordered_dynamic_next (istart, iend);
7821debfc3dSmrg     case GFS_GUIDED:
7831debfc3dSmrg       return gomp_loop_ull_ordered_guided_next (istart, iend);
7841debfc3dSmrg     default:
7851debfc3dSmrg       abort ();
7861debfc3dSmrg     }
7871debfc3dSmrg }
7881debfc3dSmrg 
7891debfc3dSmrg /* We use static functions above so that we're sure that the "runtime"
7901debfc3dSmrg    function can defer to the proper routine without interposition.  We
7911debfc3dSmrg    export the static function with a strong alias when possible, or with
7921debfc3dSmrg    a wrapper function otherwise.  */
7931debfc3dSmrg 
7941debfc3dSmrg #ifdef HAVE_ATTRIBUTE_ALIAS
7951debfc3dSmrg extern __typeof(gomp_loop_ull_static_start) GOMP_loop_ull_static_start
7961debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_static_start")));
7971debfc3dSmrg extern __typeof(gomp_loop_ull_dynamic_start) GOMP_loop_ull_dynamic_start
7981debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_dynamic_start")));
7991debfc3dSmrg extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_guided_start
8001debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_guided_start")));
8011debfc3dSmrg extern __typeof(gomp_loop_ull_dynamic_start) GOMP_loop_ull_nonmonotonic_dynamic_start
8021debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_dynamic_start")));
8031debfc3dSmrg extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_nonmonotonic_guided_start
8041debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_guided_start")));
805c0a68be4Smrg extern __typeof(GOMP_loop_ull_runtime_start) GOMP_loop_ull_nonmonotonic_runtime_start
806c0a68be4Smrg 	__attribute__((alias ("GOMP_loop_ull_runtime_start")));
807c0a68be4Smrg extern __typeof(GOMP_loop_ull_runtime_start) GOMP_loop_ull_maybe_nonmonotonic_runtime_start
808c0a68be4Smrg 	__attribute__((alias ("GOMP_loop_ull_runtime_start")));
8091debfc3dSmrg 
8101debfc3dSmrg extern __typeof(gomp_loop_ull_ordered_static_start) GOMP_loop_ull_ordered_static_start
8111debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_ordered_static_start")));
8121debfc3dSmrg extern __typeof(gomp_loop_ull_ordered_dynamic_start) GOMP_loop_ull_ordered_dynamic_start
8131debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_ordered_dynamic_start")));
8141debfc3dSmrg extern __typeof(gomp_loop_ull_ordered_guided_start) GOMP_loop_ull_ordered_guided_start
8151debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_ordered_guided_start")));
8161debfc3dSmrg 
8171debfc3dSmrg extern __typeof(gomp_loop_ull_doacross_static_start) GOMP_loop_ull_doacross_static_start
8181debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_doacross_static_start")));
8191debfc3dSmrg extern __typeof(gomp_loop_ull_doacross_dynamic_start) GOMP_loop_ull_doacross_dynamic_start
8201debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_doacross_dynamic_start")));
8211debfc3dSmrg extern __typeof(gomp_loop_ull_doacross_guided_start) GOMP_loop_ull_doacross_guided_start
8221debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_doacross_guided_start")));
8231debfc3dSmrg 
8241debfc3dSmrg extern __typeof(gomp_loop_ull_static_next) GOMP_loop_ull_static_next
8251debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_static_next")));
8261debfc3dSmrg extern __typeof(gomp_loop_ull_dynamic_next) GOMP_loop_ull_dynamic_next
8271debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_dynamic_next")));
8281debfc3dSmrg extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_guided_next
8291debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_guided_next")));
8301debfc3dSmrg extern __typeof(gomp_loop_ull_dynamic_next) GOMP_loop_ull_nonmonotonic_dynamic_next
8311debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_dynamic_next")));
8321debfc3dSmrg extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_nonmonotonic_guided_next
8331debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_guided_next")));
834c0a68be4Smrg extern __typeof(GOMP_loop_ull_runtime_next) GOMP_loop_ull_nonmonotonic_runtime_next
835c0a68be4Smrg 	__attribute__((alias ("GOMP_loop_ull_runtime_next")));
836c0a68be4Smrg extern __typeof(GOMP_loop_ull_runtime_next) GOMP_loop_ull_maybe_nonmonotonic_runtime_next
837c0a68be4Smrg 	__attribute__((alias ("GOMP_loop_ull_runtime_next")));
8381debfc3dSmrg 
8391debfc3dSmrg extern __typeof(gomp_loop_ull_ordered_static_next) GOMP_loop_ull_ordered_static_next
8401debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_ordered_static_next")));
8411debfc3dSmrg extern __typeof(gomp_loop_ull_ordered_dynamic_next) GOMP_loop_ull_ordered_dynamic_next
8421debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_ordered_dynamic_next")));
8431debfc3dSmrg extern __typeof(gomp_loop_ull_ordered_guided_next) GOMP_loop_ull_ordered_guided_next
8441debfc3dSmrg 	__attribute__((alias ("gomp_loop_ull_ordered_guided_next")));
8451debfc3dSmrg #else
8461debfc3dSmrg bool
GOMP_loop_ull_static_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)8471debfc3dSmrg GOMP_loop_ull_static_start (bool up, gomp_ull start, gomp_ull end,
8481debfc3dSmrg 			    gomp_ull incr, gomp_ull chunk_size,
8491debfc3dSmrg 			    gomp_ull *istart, gomp_ull *iend)
8501debfc3dSmrg {
8511debfc3dSmrg   return gomp_loop_ull_static_start (up, start, end, incr, chunk_size, istart,
8521debfc3dSmrg 				     iend);
8531debfc3dSmrg }
8541debfc3dSmrg 
8551debfc3dSmrg bool
GOMP_loop_ull_dynamic_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)8561debfc3dSmrg GOMP_loop_ull_dynamic_start (bool up, gomp_ull start, gomp_ull end,
8571debfc3dSmrg 			     gomp_ull incr, gomp_ull chunk_size,
8581debfc3dSmrg 			     gomp_ull *istart, gomp_ull *iend)
8591debfc3dSmrg {
8601debfc3dSmrg   return gomp_loop_ull_dynamic_start (up, start, end, incr, chunk_size, istart,
8611debfc3dSmrg 				      iend);
8621debfc3dSmrg }
8631debfc3dSmrg 
8641debfc3dSmrg bool
GOMP_loop_ull_guided_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)8651debfc3dSmrg GOMP_loop_ull_guided_start (bool up, gomp_ull start, gomp_ull end,
8661debfc3dSmrg 			    gomp_ull incr, gomp_ull chunk_size,
8671debfc3dSmrg 			    gomp_ull *istart, gomp_ull *iend)
8681debfc3dSmrg {
8691debfc3dSmrg   return gomp_loop_ull_guided_start (up, start, end, incr, chunk_size, istart,
8701debfc3dSmrg 				     iend);
8711debfc3dSmrg }
8721debfc3dSmrg 
8731debfc3dSmrg bool
GOMP_loop_ull_nonmonotonic_dynamic_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)8741debfc3dSmrg GOMP_loop_ull_nonmonotonic_dynamic_start (bool up, gomp_ull start,
8751debfc3dSmrg 					  gomp_ull end, gomp_ull incr,
8761debfc3dSmrg 					  gomp_ull chunk_size,
8771debfc3dSmrg 					  gomp_ull *istart, gomp_ull *iend)
8781debfc3dSmrg {
8791debfc3dSmrg   return gomp_loop_ull_dynamic_start (up, start, end, incr, chunk_size, istart,
8801debfc3dSmrg 				      iend);
8811debfc3dSmrg }
8821debfc3dSmrg 
8831debfc3dSmrg bool
GOMP_loop_ull_nonmonotonic_guided_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)8841debfc3dSmrg GOMP_loop_ull_nonmonotonic_guided_start (bool up, gomp_ull start, gomp_ull end,
8851debfc3dSmrg 					 gomp_ull incr, gomp_ull chunk_size,
8861debfc3dSmrg 					 gomp_ull *istart, gomp_ull *iend)
8871debfc3dSmrg {
8881debfc3dSmrg   return gomp_loop_ull_guided_start (up, start, end, incr, chunk_size, istart,
8891debfc3dSmrg 				     iend);
8901debfc3dSmrg }
8911debfc3dSmrg 
8921debfc3dSmrg bool
GOMP_loop_ull_nonmonotonic_runtime_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull * istart,gomp_ull * iend)893c0a68be4Smrg GOMP_loop_ull_nonmonotonic_runtime_start (bool up, gomp_ull start,
894c0a68be4Smrg 					  gomp_ull end, gomp_ull incr,
895c0a68be4Smrg 					  gomp_ull *istart, gomp_ull *iend)
896c0a68be4Smrg {
897c0a68be4Smrg   return GOMP_loop_ull_runtime_start (up, start, end, incr, istart, iend);
898c0a68be4Smrg }
899c0a68be4Smrg 
900c0a68be4Smrg bool
GOMP_loop_ull_maybe_nonmonotonic_runtime_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull * istart,gomp_ull * iend)901c0a68be4Smrg GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool up, gomp_ull start,
902c0a68be4Smrg 						gomp_ull end, gomp_ull incr,
903c0a68be4Smrg 						gomp_ull *istart,
904c0a68be4Smrg 						gomp_ull *iend)
905c0a68be4Smrg {
906c0a68be4Smrg   return GOMP_loop_ull_runtime_start (up, start, end, incr, istart, iend);
907c0a68be4Smrg }
908c0a68be4Smrg 
909c0a68be4Smrg bool
GOMP_loop_ull_ordered_static_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)9101debfc3dSmrg GOMP_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end,
9111debfc3dSmrg 				    gomp_ull incr, gomp_ull chunk_size,
9121debfc3dSmrg 				    gomp_ull *istart, gomp_ull *iend)
9131debfc3dSmrg {
9141debfc3dSmrg   return gomp_loop_ull_ordered_static_start (up, start, end, incr, chunk_size,
9151debfc3dSmrg 					     istart, iend);
9161debfc3dSmrg }
9171debfc3dSmrg 
9181debfc3dSmrg bool
GOMP_loop_ull_ordered_dynamic_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)9191debfc3dSmrg GOMP_loop_ull_ordered_dynamic_start (bool up, gomp_ull start, gomp_ull end,
9201debfc3dSmrg 				     gomp_ull incr, gomp_ull chunk_size,
9211debfc3dSmrg 				     gomp_ull *istart, gomp_ull *iend)
9221debfc3dSmrg {
9231debfc3dSmrg   return gomp_loop_ull_ordered_dynamic_start (up, start, end, incr, chunk_size,
9241debfc3dSmrg 					      istart, iend);
9251debfc3dSmrg }
9261debfc3dSmrg 
9271debfc3dSmrg bool
GOMP_loop_ull_ordered_guided_start(bool up,gomp_ull start,gomp_ull end,gomp_ull incr,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)9281debfc3dSmrg GOMP_loop_ull_ordered_guided_start (bool up, gomp_ull start, gomp_ull end,
9291debfc3dSmrg 				    gomp_ull incr, gomp_ull chunk_size,
9301debfc3dSmrg 				    gomp_ull *istart, gomp_ull *iend)
9311debfc3dSmrg {
9321debfc3dSmrg   return gomp_loop_ull_ordered_guided_start (up, start, end, incr, chunk_size,
9331debfc3dSmrg 					     istart, iend);
9341debfc3dSmrg }
9351debfc3dSmrg 
9361debfc3dSmrg bool
GOMP_loop_ull_doacross_static_start(unsigned ncounts,gomp_ull * counts,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)9371debfc3dSmrg GOMP_loop_ull_doacross_static_start (unsigned ncounts, gomp_ull *counts,
9381debfc3dSmrg 				     gomp_ull chunk_size, gomp_ull *istart,
9391debfc3dSmrg 				     gomp_ull *iend)
9401debfc3dSmrg {
9411debfc3dSmrg   return gomp_loop_ull_doacross_static_start (ncounts, counts, chunk_size,
9421debfc3dSmrg 					      istart, iend);
9431debfc3dSmrg }
9441debfc3dSmrg 
9451debfc3dSmrg bool
GOMP_loop_ull_doacross_dynamic_start(unsigned ncounts,gomp_ull * counts,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)9461debfc3dSmrg GOMP_loop_ull_doacross_dynamic_start (unsigned ncounts, gomp_ull *counts,
9471debfc3dSmrg 				      gomp_ull chunk_size, gomp_ull *istart,
9481debfc3dSmrg 				      gomp_ull *iend)
9491debfc3dSmrg {
9501debfc3dSmrg   return gomp_loop_ull_doacross_dynamic_start (ncounts, counts, chunk_size,
9511debfc3dSmrg 					       istart, iend);
9521debfc3dSmrg }
9531debfc3dSmrg 
9541debfc3dSmrg bool
GOMP_loop_ull_doacross_guided_start(unsigned ncounts,gomp_ull * counts,gomp_ull chunk_size,gomp_ull * istart,gomp_ull * iend)9551debfc3dSmrg GOMP_loop_ull_doacross_guided_start (unsigned ncounts, gomp_ull *counts,
9561debfc3dSmrg 				     gomp_ull chunk_size, gomp_ull *istart,
9571debfc3dSmrg 				     gomp_ull *iend)
9581debfc3dSmrg {
9591debfc3dSmrg   return gomp_loop_ull_doacross_guided_start (ncounts, counts, chunk_size,
9601debfc3dSmrg 					      istart, iend);
9611debfc3dSmrg }
9621debfc3dSmrg 
9631debfc3dSmrg bool
GOMP_loop_ull_static_next(gomp_ull * istart,gomp_ull * iend)9641debfc3dSmrg GOMP_loop_ull_static_next (gomp_ull *istart, gomp_ull *iend)
9651debfc3dSmrg {
9661debfc3dSmrg   return gomp_loop_ull_static_next (istart, iend);
9671debfc3dSmrg }
9681debfc3dSmrg 
9691debfc3dSmrg bool
GOMP_loop_ull_dynamic_next(gomp_ull * istart,gomp_ull * iend)9701debfc3dSmrg GOMP_loop_ull_dynamic_next (gomp_ull *istart, gomp_ull *iend)
9711debfc3dSmrg {
9721debfc3dSmrg   return gomp_loop_ull_dynamic_next (istart, iend);
9731debfc3dSmrg }
9741debfc3dSmrg 
9751debfc3dSmrg bool
GOMP_loop_ull_guided_next(gomp_ull * istart,gomp_ull * iend)9761debfc3dSmrg GOMP_loop_ull_guided_next (gomp_ull *istart, gomp_ull *iend)
9771debfc3dSmrg {
9781debfc3dSmrg   return gomp_loop_ull_guided_next (istart, iend);
9791debfc3dSmrg }
9801debfc3dSmrg 
9811debfc3dSmrg bool
GOMP_loop_ull_nonmonotonic_dynamic_next(gomp_ull * istart,gomp_ull * iend)9821debfc3dSmrg GOMP_loop_ull_nonmonotonic_dynamic_next (gomp_ull *istart, gomp_ull *iend)
9831debfc3dSmrg {
9841debfc3dSmrg   return gomp_loop_ull_dynamic_next (istart, iend);
9851debfc3dSmrg }
9861debfc3dSmrg 
9871debfc3dSmrg bool
GOMP_loop_ull_nonmonotonic_guided_next(gomp_ull * istart,gomp_ull * iend)9881debfc3dSmrg GOMP_loop_ull_nonmonotonic_guided_next (gomp_ull *istart, gomp_ull *iend)
9891debfc3dSmrg {
9901debfc3dSmrg   return gomp_loop_ull_guided_next (istart, iend);
9911debfc3dSmrg }
9921debfc3dSmrg 
9931debfc3dSmrg bool
GOMP_loop_ull_nonmonotonic_runtime_next(gomp_ull * istart,gomp_ull * iend)994c0a68be4Smrg GOMP_loop_ull_nonmonotonic_runtime_next (gomp_ull *istart, gomp_ull *iend)
995c0a68be4Smrg {
996c0a68be4Smrg   return GOMP_loop_ull_runtime_next (istart, iend);
997c0a68be4Smrg }
998c0a68be4Smrg 
999c0a68be4Smrg bool
GOMP_loop_ull_maybe_nonmonotonic_runtime_next(gomp_ull * istart,gomp_ull * iend)1000c0a68be4Smrg GOMP_loop_ull_maybe_nonmonotonic_runtime_next (gomp_ull *istart,
1001c0a68be4Smrg 					       gomp_ull *iend)
1002c0a68be4Smrg {
1003c0a68be4Smrg   return GOMP_loop_ull_runtime_next (istart, iend);
1004c0a68be4Smrg }
1005c0a68be4Smrg 
1006c0a68be4Smrg bool
GOMP_loop_ull_ordered_static_next(gomp_ull * istart,gomp_ull * iend)10071debfc3dSmrg GOMP_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend)
10081debfc3dSmrg {
10091debfc3dSmrg   return gomp_loop_ull_ordered_static_next (istart, iend);
10101debfc3dSmrg }
10111debfc3dSmrg 
10121debfc3dSmrg bool
GOMP_loop_ull_ordered_dynamic_next(gomp_ull * istart,gomp_ull * iend)10131debfc3dSmrg GOMP_loop_ull_ordered_dynamic_next (gomp_ull *istart, gomp_ull *iend)
10141debfc3dSmrg {
10151debfc3dSmrg   return gomp_loop_ull_ordered_dynamic_next (istart, iend);
10161debfc3dSmrg }
10171debfc3dSmrg 
10181debfc3dSmrg bool
GOMP_loop_ull_ordered_guided_next(gomp_ull * istart,gomp_ull * iend)10191debfc3dSmrg GOMP_loop_ull_ordered_guided_next (gomp_ull *istart, gomp_ull *iend)
10201debfc3dSmrg {
10211debfc3dSmrg   return gomp_loop_ull_ordered_guided_next (istart, iend);
10221debfc3dSmrg }
10231debfc3dSmrg #endif
1024