1 /* Copyright (C) 2005-2021 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
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)
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
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 /* This file handles the LOOP (FOR/DO) construct. */
33 ialias (GOMP_loop_ull_runtime_next
)
34 ialias_redirect (GOMP_taskgroup_reduction_register
)
36 typedef unsigned long long gomp_ull
;
38 /* Initialize the given work share construct from the given arguments. */
41 gomp_loop_ull_init (struct gomp_work_share
*ws
, bool up
, gomp_ull start
,
42 gomp_ull end
, gomp_ull incr
, enum gomp_schedule_type sched
,
46 ws
->chunk_size_ull
= chunk_size
;
47 /* Canonicalize loops that have zero iterations to ->next == ->end. */
48 ws
->end_ull
= ((up
&& start
> end
) || (!up
&& start
< end
))
53 if (sched
== GFS_DYNAMIC
)
55 ws
->chunk_size_ull
*= incr
;
57 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
59 /* For dynamic scheduling prepare things to make each iteration
61 struct gomp_thread
*thr
= gomp_thread ();
62 struct gomp_team
*team
= thr
->ts
.team
;
63 long nthreads
= team
? team
->nthreads
: 1;
65 if (__builtin_expect (up
, 1))
67 /* Cheap overflow protection. */
68 if (__builtin_expect ((nthreads
| ws
->chunk_size_ull
)
69 < 1ULL << (sizeof (gomp_ull
)
70 * __CHAR_BIT__
/ 2 - 1), 1))
71 ws
->mode
= ws
->end_ull
< (__LONG_LONG_MAX__
* 2ULL + 1
72 - (nthreads
+ 1) * ws
->chunk_size_ull
);
74 /* Cheap overflow protection. */
75 else if (__builtin_expect ((nthreads
| -ws
->chunk_size_ull
)
76 < 1ULL << (sizeof (gomp_ull
)
77 * __CHAR_BIT__
/ 2 - 1), 1))
78 ws
->mode
= ws
->end_ull
> ((nthreads
+ 1) * -ws
->chunk_size_ull
79 - (__LONG_LONG_MAX__
* 2ULL + 1));
87 /* The *_start routines are called when first encountering a loop construct
88 that is not bound directly to a parallel construct. The first thread
89 that arrives will create the work-share construct; subsequent threads
90 will see the construct exists and allocate work from it.
92 START, END, INCR are the bounds of the loop; due to the restrictions of
93 OpenMP, these values must be the same in every thread. This is not
94 verified (nor is it entirely verifiable, since START is not necessarily
95 retained intact in the work-share data structure). CHUNK_SIZE is the
96 scheduling parameter; again this must be identical in all threads.
98 Returns true if there's any work for this thread to perform. If so,
99 *ISTART and *IEND are filled with the bounds of the iteration block
100 allocated to this thread. Returns false if all work was assigned to
101 other threads prior to this thread's arrival. */
104 gomp_loop_ull_static_start (bool up
, gomp_ull start
, gomp_ull end
,
105 gomp_ull incr
, gomp_ull chunk_size
,
106 gomp_ull
*istart
, gomp_ull
*iend
)
108 struct gomp_thread
*thr
= gomp_thread ();
110 thr
->ts
.static_trip
= 0;
111 if (gomp_work_share_start (0))
113 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
114 GFS_STATIC
, chunk_size
);
115 gomp_work_share_init_done ();
118 return !gomp_iter_ull_static_next (istart
, iend
);
122 gomp_loop_ull_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
123 gomp_ull incr
, gomp_ull chunk_size
,
124 gomp_ull
*istart
, gomp_ull
*iend
)
126 struct gomp_thread
*thr
= gomp_thread ();
129 if (gomp_work_share_start (0))
131 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
132 GFS_DYNAMIC
, chunk_size
);
133 gomp_work_share_init_done ();
136 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
137 ret
= gomp_iter_ull_dynamic_next (istart
, iend
);
139 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
140 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
141 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
148 gomp_loop_ull_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
149 gomp_ull incr
, gomp_ull chunk_size
,
150 gomp_ull
*istart
, gomp_ull
*iend
)
152 struct gomp_thread
*thr
= gomp_thread ();
155 if (gomp_work_share_start (0))
157 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
158 GFS_GUIDED
, chunk_size
);
159 gomp_work_share_init_done ();
162 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
163 ret
= gomp_iter_ull_guided_next (istart
, iend
);
165 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
166 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
167 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
174 GOMP_loop_ull_runtime_start (bool up
, gomp_ull start
, gomp_ull end
,
175 gomp_ull incr
, gomp_ull
*istart
, gomp_ull
*iend
)
177 struct gomp_task_icv
*icv
= gomp_icv (false);
178 switch (icv
->run_sched_var
& ~GFS_MONOTONIC
)
181 return gomp_loop_ull_static_start (up
, start
, end
, incr
,
182 icv
->run_sched_chunk_size
,
185 return gomp_loop_ull_dynamic_start (up
, start
, end
, incr
,
186 icv
->run_sched_chunk_size
,
189 return gomp_loop_ull_guided_start (up
, start
, end
, incr
,
190 icv
->run_sched_chunk_size
,
193 /* For now map to schedule(static), later on we could play with feedback
195 return gomp_loop_ull_static_start (up
, start
, end
, incr
,
203 gomp_adjust_sched (long sched
, gomp_ull
*chunk_size
)
205 sched
&= ~GFS_MONOTONIC
;
212 /* GFS_RUNTIME is used for runtime schedule without monotonic
213 or nonmonotonic modifiers on the clause.
214 GFS_RUNTIME|GFS_MONOTONIC for runtime schedule with monotonic
217 /* GFS_AUTO is used for runtime schedule with nonmonotonic
221 struct gomp_task_icv
*icv
= gomp_icv (false);
222 sched
= icv
->run_sched_var
& ~GFS_MONOTONIC
;
228 *chunk_size
= icv
->run_sched_chunk_size
;
245 GOMP_loop_ull_start (bool up
, gomp_ull start
, gomp_ull end
,
246 gomp_ull incr
, long sched
, gomp_ull chunk_size
,
247 gomp_ull
*istart
, gomp_ull
*iend
,
248 uintptr_t *reductions
, void **mem
)
250 struct gomp_thread
*thr
= gomp_thread ();
252 thr
->ts
.static_trip
= 0;
254 gomp_workshare_taskgroup_start ();
255 if (gomp_work_share_start (0))
257 sched
= gomp_adjust_sched (sched
, &chunk_size
);
258 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
262 GOMP_taskgroup_reduction_register (reductions
);
263 thr
->task
->taskgroup
->workshare
= true;
264 thr
->ts
.work_share
->task_reductions
= reductions
;
268 uintptr_t size
= (uintptr_t) *mem
;
269 #define INLINE_ORDERED_TEAM_IDS_OFF \
270 ((offsetof (struct gomp_work_share, inline_ordered_team_ids) \
271 + __alignof__ (long long) - 1) & ~(__alignof__ (long long) - 1))
272 if (size
> (sizeof (struct gomp_work_share
)
273 - INLINE_ORDERED_TEAM_IDS_OFF
))
275 = (void *) (thr
->ts
.work_share
->ordered_team_ids
276 = gomp_malloc_cleared (size
));
278 *mem
= memset (((char *) thr
->ts
.work_share
)
279 + INLINE_ORDERED_TEAM_IDS_OFF
, '\0', size
);
281 gomp_work_share_init_done ();
287 uintptr_t *first_reductions
= thr
->ts
.work_share
->task_reductions
;
288 gomp_workshare_task_reduction_register (reductions
,
293 if ((offsetof (struct gomp_work_share
, inline_ordered_team_ids
)
294 & (__alignof__ (long long) - 1)) == 0)
295 *mem
= (void *) thr
->ts
.work_share
->ordered_team_ids
;
298 uintptr_t p
= (uintptr_t) thr
->ts
.work_share
->ordered_team_ids
;
299 p
+= __alignof__ (long long) - 1;
300 p
&= ~(__alignof__ (long long) - 1);
306 return ialias_call (GOMP_loop_ull_runtime_next
) (istart
, iend
);
309 /* The *_ordered_*_start routines are similar. The only difference is that
310 this work-share construct is initialized to expect an ORDERED section. */
313 gomp_loop_ull_ordered_static_start (bool up
, gomp_ull start
, gomp_ull end
,
314 gomp_ull incr
, gomp_ull chunk_size
,
315 gomp_ull
*istart
, gomp_ull
*iend
)
317 struct gomp_thread
*thr
= gomp_thread ();
319 thr
->ts
.static_trip
= 0;
320 if (gomp_work_share_start (1))
322 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
323 GFS_STATIC
, chunk_size
);
324 gomp_ordered_static_init ();
325 gomp_work_share_init_done ();
328 return !gomp_iter_ull_static_next (istart
, iend
);
332 gomp_loop_ull_ordered_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
333 gomp_ull incr
, gomp_ull chunk_size
,
334 gomp_ull
*istart
, gomp_ull
*iend
)
336 struct gomp_thread
*thr
= gomp_thread ();
339 if (gomp_work_share_start (1))
341 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
342 GFS_DYNAMIC
, chunk_size
);
343 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
344 gomp_work_share_init_done ();
347 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
349 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
351 gomp_ordered_first ();
352 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
358 gomp_loop_ull_ordered_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
359 gomp_ull incr
, gomp_ull chunk_size
,
360 gomp_ull
*istart
, gomp_ull
*iend
)
362 struct gomp_thread
*thr
= gomp_thread ();
365 if (gomp_work_share_start (1))
367 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
368 GFS_GUIDED
, chunk_size
);
369 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
370 gomp_work_share_init_done ();
373 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
375 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
377 gomp_ordered_first ();
378 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
384 GOMP_loop_ull_ordered_runtime_start (bool up
, gomp_ull start
, gomp_ull end
,
385 gomp_ull incr
, gomp_ull
*istart
,
388 struct gomp_task_icv
*icv
= gomp_icv (false);
389 switch (icv
->run_sched_var
& ~GFS_MONOTONIC
)
392 return gomp_loop_ull_ordered_static_start (up
, start
, end
, incr
,
393 icv
->run_sched_chunk_size
,
396 return gomp_loop_ull_ordered_dynamic_start (up
, start
, end
, incr
,
397 icv
->run_sched_chunk_size
,
400 return gomp_loop_ull_ordered_guided_start (up
, start
, end
, incr
,
401 icv
->run_sched_chunk_size
,
404 /* For now map to schedule(static), later on we could play with feedback
406 return gomp_loop_ull_ordered_static_start (up
, start
, end
, incr
,
414 GOMP_loop_ull_ordered_start (bool up
, gomp_ull start
, gomp_ull end
,
415 gomp_ull incr
, long sched
, gomp_ull chunk_size
,
416 gomp_ull
*istart
, gomp_ull
*iend
,
417 uintptr_t *reductions
, void **mem
)
419 struct gomp_thread
*thr
= gomp_thread ();
423 thr
->ts
.static_trip
= 0;
425 gomp_workshare_taskgroup_start ();
427 ordered
+= (uintptr_t) *mem
;
428 if (gomp_work_share_start (ordered
))
430 sched
= gomp_adjust_sched (sched
, &chunk_size
);
431 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
435 GOMP_taskgroup_reduction_register (reductions
);
436 thr
->task
->taskgroup
->workshare
= true;
437 thr
->ts
.work_share
->task_reductions
= reductions
;
439 if (sched
== GFS_STATIC
)
440 gomp_ordered_static_init ();
442 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
443 gomp_work_share_init_done ();
449 uintptr_t *first_reductions
= thr
->ts
.work_share
->task_reductions
;
450 gomp_workshare_task_reduction_register (reductions
,
453 sched
= thr
->ts
.work_share
->sched
;
454 if (sched
!= GFS_STATIC
)
455 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
461 = (uintptr_t) (thr
->ts
.work_share
->ordered_team_ids
462 + (thr
->ts
.team
? thr
->ts
.team
->nthreads
: 1));
463 p
+= __alignof__ (long long) - 1;
464 p
&= ~(__alignof__ (long long) - 1);
472 return !gomp_iter_ull_static_next (istart
, iend
);
474 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
477 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
484 gomp_ordered_first ();
485 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
489 /* The *_doacross_*_start routines are similar. The only difference is that
490 this work-share construct is initialized to expect an ORDERED(N) - DOACROSS
491 section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1
492 and other COUNTS array elements tell the library number of iterations
493 in the ordered inner loops. */
496 gomp_loop_ull_doacross_static_start (unsigned ncounts
, gomp_ull
*counts
,
497 gomp_ull chunk_size
, gomp_ull
*istart
,
500 struct gomp_thread
*thr
= gomp_thread ();
502 thr
->ts
.static_trip
= 0;
503 if (gomp_work_share_start (0))
505 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
506 GFS_STATIC
, chunk_size
);
507 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, 0);
508 gomp_work_share_init_done ();
511 return !gomp_iter_ull_static_next (istart
, iend
);
515 gomp_loop_ull_doacross_dynamic_start (unsigned ncounts
, gomp_ull
*counts
,
516 gomp_ull chunk_size
, gomp_ull
*istart
,
519 struct gomp_thread
*thr
= gomp_thread ();
522 if (gomp_work_share_start (0))
524 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
525 GFS_DYNAMIC
, chunk_size
);
526 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, 0);
527 gomp_work_share_init_done ();
530 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
531 ret
= gomp_iter_ull_dynamic_next (istart
, iend
);
533 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
534 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
535 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
542 gomp_loop_ull_doacross_guided_start (unsigned ncounts
, gomp_ull
*counts
,
543 gomp_ull chunk_size
, gomp_ull
*istart
,
546 struct gomp_thread
*thr
= gomp_thread ();
549 if (gomp_work_share_start (0))
551 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
552 GFS_GUIDED
, chunk_size
);
553 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, 0);
554 gomp_work_share_init_done ();
557 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
558 ret
= gomp_iter_ull_guided_next (istart
, iend
);
560 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
561 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
562 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
569 GOMP_loop_ull_doacross_runtime_start (unsigned ncounts
, gomp_ull
*counts
,
570 gomp_ull
*istart
, gomp_ull
*iend
)
572 struct gomp_task_icv
*icv
= gomp_icv (false);
573 switch (icv
->run_sched_var
& ~GFS_MONOTONIC
)
576 return gomp_loop_ull_doacross_static_start (ncounts
, counts
,
577 icv
->run_sched_chunk_size
,
580 return gomp_loop_ull_doacross_dynamic_start (ncounts
, counts
,
581 icv
->run_sched_chunk_size
,
584 return gomp_loop_ull_doacross_guided_start (ncounts
, counts
,
585 icv
->run_sched_chunk_size
,
588 /* For now map to schedule(static), later on we could play with feedback
590 return gomp_loop_ull_doacross_static_start (ncounts
, counts
,
598 GOMP_loop_ull_doacross_start (unsigned ncounts
, gomp_ull
*counts
,
599 long sched
, gomp_ull chunk_size
,
600 gomp_ull
*istart
, gomp_ull
*iend
,
601 uintptr_t *reductions
, void **mem
)
603 struct gomp_thread
*thr
= gomp_thread ();
605 thr
->ts
.static_trip
= 0;
607 gomp_workshare_taskgroup_start ();
608 if (gomp_work_share_start (0))
612 extra
= (uintptr_t) *mem
;
613 sched
= gomp_adjust_sched (sched
, &chunk_size
);
614 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
616 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, extra
);
619 GOMP_taskgroup_reduction_register (reductions
);
620 thr
->task
->taskgroup
->workshare
= true;
621 thr
->ts
.work_share
->task_reductions
= reductions
;
623 gomp_work_share_init_done ();
629 uintptr_t *first_reductions
= thr
->ts
.work_share
->task_reductions
;
630 gomp_workshare_task_reduction_register (reductions
,
633 sched
= thr
->ts
.work_share
->sched
;
637 *mem
= thr
->ts
.work_share
->doacross
->extra
;
639 return ialias_call (GOMP_loop_ull_runtime_next
) (istart
, iend
);
642 /* The *_next routines are called when the thread completes processing of
643 the iteration block currently assigned to it. If the work-share
644 construct is bound directly to a parallel construct, then the iteration
645 bounds may have been set up before the parallel. In which case, this
646 may be the first iteration for the thread.
648 Returns true if there is work remaining to be performed; *ISTART and
649 *IEND are filled with a new iteration block. Returns false if all work
650 has been assigned. */
653 gomp_loop_ull_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
655 return !gomp_iter_ull_static_next (istart
, iend
);
659 gomp_loop_ull_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
663 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
664 ret
= gomp_iter_ull_dynamic_next (istart
, iend
);
666 struct gomp_thread
*thr
= gomp_thread ();
667 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
668 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
669 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
676 gomp_loop_ull_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
680 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
681 ret
= gomp_iter_ull_guided_next (istart
, iend
);
683 struct gomp_thread
*thr
= gomp_thread ();
684 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
685 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
686 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
693 GOMP_loop_ull_runtime_next (gomp_ull
*istart
, gomp_ull
*iend
)
695 struct gomp_thread
*thr
= gomp_thread ();
697 switch (thr
->ts
.work_share
->sched
)
701 return gomp_loop_ull_static_next (istart
, iend
);
703 return gomp_loop_ull_dynamic_next (istart
, iend
);
705 return gomp_loop_ull_guided_next (istart
, iend
);
711 /* The *_ordered_*_next routines are called when the thread completes
712 processing of the iteration block currently assigned to it.
714 Returns true if there is work remaining to be performed; *ISTART and
715 *IEND are filled with a new iteration block. Returns false if all work
716 has been assigned. */
719 gomp_loop_ull_ordered_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
721 struct gomp_thread
*thr
= gomp_thread ();
724 gomp_ordered_sync ();
725 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
726 test
= gomp_iter_ull_static_next (istart
, iend
);
728 gomp_ordered_static_next ();
729 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
735 gomp_loop_ull_ordered_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
737 struct gomp_thread
*thr
= gomp_thread ();
740 gomp_ordered_sync ();
741 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
742 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
744 gomp_ordered_next ();
746 gomp_ordered_last ();
747 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
753 gomp_loop_ull_ordered_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
755 struct gomp_thread
*thr
= gomp_thread ();
758 gomp_ordered_sync ();
759 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
760 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
762 gomp_ordered_next ();
764 gomp_ordered_last ();
765 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
771 GOMP_loop_ull_ordered_runtime_next (gomp_ull
*istart
, gomp_ull
*iend
)
773 struct gomp_thread
*thr
= gomp_thread ();
775 switch (thr
->ts
.work_share
->sched
)
779 return gomp_loop_ull_ordered_static_next (istart
, iend
);
781 return gomp_loop_ull_ordered_dynamic_next (istart
, iend
);
783 return gomp_loop_ull_ordered_guided_next (istart
, iend
);
789 /* We use static functions above so that we're sure that the "runtime"
790 function can defer to the proper routine without interposition. We
791 export the static function with a strong alias when possible, or with
792 a wrapper function otherwise. */
794 #ifdef HAVE_ATTRIBUTE_ALIAS
795 extern __typeof(gomp_loop_ull_static_start
) GOMP_loop_ull_static_start
796 __attribute__((alias ("gomp_loop_ull_static_start")));
797 extern __typeof(gomp_loop_ull_dynamic_start
) GOMP_loop_ull_dynamic_start
798 __attribute__((alias ("gomp_loop_ull_dynamic_start")));
799 extern __typeof(gomp_loop_ull_guided_start
) GOMP_loop_ull_guided_start
800 __attribute__((alias ("gomp_loop_ull_guided_start")));
801 extern __typeof(gomp_loop_ull_dynamic_start
) GOMP_loop_ull_nonmonotonic_dynamic_start
802 __attribute__((alias ("gomp_loop_ull_dynamic_start")));
803 extern __typeof(gomp_loop_ull_guided_start
) GOMP_loop_ull_nonmonotonic_guided_start
804 __attribute__((alias ("gomp_loop_ull_guided_start")));
805 extern __typeof(GOMP_loop_ull_runtime_start
) GOMP_loop_ull_nonmonotonic_runtime_start
806 __attribute__((alias ("GOMP_loop_ull_runtime_start")));
807 extern __typeof(GOMP_loop_ull_runtime_start
) GOMP_loop_ull_maybe_nonmonotonic_runtime_start
808 __attribute__((alias ("GOMP_loop_ull_runtime_start")));
810 extern __typeof(gomp_loop_ull_ordered_static_start
) GOMP_loop_ull_ordered_static_start
811 __attribute__((alias ("gomp_loop_ull_ordered_static_start")));
812 extern __typeof(gomp_loop_ull_ordered_dynamic_start
) GOMP_loop_ull_ordered_dynamic_start
813 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_start")));
814 extern __typeof(gomp_loop_ull_ordered_guided_start
) GOMP_loop_ull_ordered_guided_start
815 __attribute__((alias ("gomp_loop_ull_ordered_guided_start")));
817 extern __typeof(gomp_loop_ull_doacross_static_start
) GOMP_loop_ull_doacross_static_start
818 __attribute__((alias ("gomp_loop_ull_doacross_static_start")));
819 extern __typeof(gomp_loop_ull_doacross_dynamic_start
) GOMP_loop_ull_doacross_dynamic_start
820 __attribute__((alias ("gomp_loop_ull_doacross_dynamic_start")));
821 extern __typeof(gomp_loop_ull_doacross_guided_start
) GOMP_loop_ull_doacross_guided_start
822 __attribute__((alias ("gomp_loop_ull_doacross_guided_start")));
824 extern __typeof(gomp_loop_ull_static_next
) GOMP_loop_ull_static_next
825 __attribute__((alias ("gomp_loop_ull_static_next")));
826 extern __typeof(gomp_loop_ull_dynamic_next
) GOMP_loop_ull_dynamic_next
827 __attribute__((alias ("gomp_loop_ull_dynamic_next")));
828 extern __typeof(gomp_loop_ull_guided_next
) GOMP_loop_ull_guided_next
829 __attribute__((alias ("gomp_loop_ull_guided_next")));
830 extern __typeof(gomp_loop_ull_dynamic_next
) GOMP_loop_ull_nonmonotonic_dynamic_next
831 __attribute__((alias ("gomp_loop_ull_dynamic_next")));
832 extern __typeof(gomp_loop_ull_guided_next
) GOMP_loop_ull_nonmonotonic_guided_next
833 __attribute__((alias ("gomp_loop_ull_guided_next")));
834 extern __typeof(GOMP_loop_ull_runtime_next
) GOMP_loop_ull_nonmonotonic_runtime_next
835 __attribute__((alias ("GOMP_loop_ull_runtime_next")));
836 extern __typeof(GOMP_loop_ull_runtime_next
) GOMP_loop_ull_maybe_nonmonotonic_runtime_next
837 __attribute__((alias ("GOMP_loop_ull_runtime_next")));
839 extern __typeof(gomp_loop_ull_ordered_static_next
) GOMP_loop_ull_ordered_static_next
840 __attribute__((alias ("gomp_loop_ull_ordered_static_next")));
841 extern __typeof(gomp_loop_ull_ordered_dynamic_next
) GOMP_loop_ull_ordered_dynamic_next
842 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_next")));
843 extern __typeof(gomp_loop_ull_ordered_guided_next
) GOMP_loop_ull_ordered_guided_next
844 __attribute__((alias ("gomp_loop_ull_ordered_guided_next")));
847 GOMP_loop_ull_static_start (bool up
, gomp_ull start
, gomp_ull end
,
848 gomp_ull incr
, gomp_ull chunk_size
,
849 gomp_ull
*istart
, gomp_ull
*iend
)
851 return gomp_loop_ull_static_start (up
, start
, end
, incr
, chunk_size
, istart
,
856 GOMP_loop_ull_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
857 gomp_ull incr
, gomp_ull chunk_size
,
858 gomp_ull
*istart
, gomp_ull
*iend
)
860 return gomp_loop_ull_dynamic_start (up
, start
, end
, incr
, chunk_size
, istart
,
865 GOMP_loop_ull_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
866 gomp_ull incr
, gomp_ull chunk_size
,
867 gomp_ull
*istart
, gomp_ull
*iend
)
869 return gomp_loop_ull_guided_start (up
, start
, end
, incr
, chunk_size
, istart
,
874 GOMP_loop_ull_nonmonotonic_dynamic_start (bool up
, gomp_ull start
,
875 gomp_ull end
, gomp_ull incr
,
877 gomp_ull
*istart
, gomp_ull
*iend
)
879 return gomp_loop_ull_dynamic_start (up
, start
, end
, incr
, chunk_size
, istart
,
884 GOMP_loop_ull_nonmonotonic_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
885 gomp_ull incr
, gomp_ull chunk_size
,
886 gomp_ull
*istart
, gomp_ull
*iend
)
888 return gomp_loop_ull_guided_start (up
, start
, end
, incr
, chunk_size
, istart
,
893 GOMP_loop_ull_nonmonotonic_runtime_start (bool up
, gomp_ull start
,
894 gomp_ull end
, gomp_ull incr
,
895 gomp_ull
*istart
, gomp_ull
*iend
)
897 return GOMP_loop_ull_runtime_start (up
, start
, end
, incr
, istart
, iend
);
901 GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool up
, gomp_ull start
,
902 gomp_ull end
, gomp_ull incr
,
906 return GOMP_loop_ull_runtime_start (up
, start
, end
, incr
, istart
, iend
);
910 GOMP_loop_ull_ordered_static_start (bool up
, gomp_ull start
, gomp_ull end
,
911 gomp_ull incr
, gomp_ull chunk_size
,
912 gomp_ull
*istart
, gomp_ull
*iend
)
914 return gomp_loop_ull_ordered_static_start (up
, start
, end
, incr
, chunk_size
,
919 GOMP_loop_ull_ordered_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
920 gomp_ull incr
, gomp_ull chunk_size
,
921 gomp_ull
*istart
, gomp_ull
*iend
)
923 return gomp_loop_ull_ordered_dynamic_start (up
, start
, end
, incr
, chunk_size
,
928 GOMP_loop_ull_ordered_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
929 gomp_ull incr
, gomp_ull chunk_size
,
930 gomp_ull
*istart
, gomp_ull
*iend
)
932 return gomp_loop_ull_ordered_guided_start (up
, start
, end
, incr
, chunk_size
,
937 GOMP_loop_ull_doacross_static_start (unsigned ncounts
, gomp_ull
*counts
,
938 gomp_ull chunk_size
, gomp_ull
*istart
,
941 return gomp_loop_ull_doacross_static_start (ncounts
, counts
, chunk_size
,
946 GOMP_loop_ull_doacross_dynamic_start (unsigned ncounts
, gomp_ull
*counts
,
947 gomp_ull chunk_size
, gomp_ull
*istart
,
950 return gomp_loop_ull_doacross_dynamic_start (ncounts
, counts
, chunk_size
,
955 GOMP_loop_ull_doacross_guided_start (unsigned ncounts
, gomp_ull
*counts
,
956 gomp_ull chunk_size
, gomp_ull
*istart
,
959 return gomp_loop_ull_doacross_guided_start (ncounts
, counts
, chunk_size
,
964 GOMP_loop_ull_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
966 return gomp_loop_ull_static_next (istart
, iend
);
970 GOMP_loop_ull_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
972 return gomp_loop_ull_dynamic_next (istart
, iend
);
976 GOMP_loop_ull_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
978 return gomp_loop_ull_guided_next (istart
, iend
);
982 GOMP_loop_ull_nonmonotonic_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
984 return gomp_loop_ull_dynamic_next (istart
, iend
);
988 GOMP_loop_ull_nonmonotonic_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
990 return gomp_loop_ull_guided_next (istart
, iend
);
994 GOMP_loop_ull_nonmonotonic_runtime_next (gomp_ull
*istart
, gomp_ull
*iend
)
996 return GOMP_loop_ull_runtime_next (istart
, iend
);
1000 GOMP_loop_ull_maybe_nonmonotonic_runtime_next (gomp_ull
*istart
,
1003 return GOMP_loop_ull_runtime_next (istart
, iend
);
1007 GOMP_loop_ull_ordered_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
1009 return gomp_loop_ull_ordered_static_next (istart
, iend
);
1013 GOMP_loop_ull_ordered_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
1015 return gomp_loop_ull_ordered_dynamic_next (istart
, iend
);
1019 GOMP_loop_ull_ordered_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
1021 return gomp_loop_ull_ordered_guided_next (istart
, iend
);