1 /* Copyright (C) 2005-2023 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 (sizeof (struct gomp_work_share
)
273 <= INLINE_ORDERED_TEAM_IDS_OFF
274 || __alignof__ (struct gomp_work_share
) < __alignof__ (long long)
275 || size
> (sizeof (struct gomp_work_share
)
276 - INLINE_ORDERED_TEAM_IDS_OFF
))
278 = (void *) (thr
->ts
.work_share
->ordered_team_ids
279 = gomp_malloc_cleared (size
));
281 *mem
= memset (((char *) thr
->ts
.work_share
)
282 + INLINE_ORDERED_TEAM_IDS_OFF
, '\0', size
);
284 gomp_work_share_init_done ();
290 uintptr_t *first_reductions
= thr
->ts
.work_share
->task_reductions
;
291 gomp_workshare_task_reduction_register (reductions
,
296 if ((offsetof (struct gomp_work_share
, inline_ordered_team_ids
)
297 & (__alignof__ (long long) - 1)) == 0)
298 *mem
= (void *) thr
->ts
.work_share
->ordered_team_ids
;
301 uintptr_t p
= (uintptr_t) thr
->ts
.work_share
->ordered_team_ids
;
302 p
+= __alignof__ (long long) - 1;
303 p
&= ~(__alignof__ (long long) - 1);
309 return ialias_call (GOMP_loop_ull_runtime_next
) (istart
, iend
);
312 /* The *_ordered_*_start routines are similar. The only difference is that
313 this work-share construct is initialized to expect an ORDERED section. */
316 gomp_loop_ull_ordered_static_start (bool up
, gomp_ull start
, gomp_ull end
,
317 gomp_ull incr
, gomp_ull chunk_size
,
318 gomp_ull
*istart
, gomp_ull
*iend
)
320 struct gomp_thread
*thr
= gomp_thread ();
322 thr
->ts
.static_trip
= 0;
323 if (gomp_work_share_start (1))
325 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
326 GFS_STATIC
, chunk_size
);
327 gomp_ordered_static_init ();
328 gomp_work_share_init_done ();
331 return !gomp_iter_ull_static_next (istart
, iend
);
335 gomp_loop_ull_ordered_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
336 gomp_ull incr
, gomp_ull chunk_size
,
337 gomp_ull
*istart
, gomp_ull
*iend
)
339 struct gomp_thread
*thr
= gomp_thread ();
342 if (gomp_work_share_start (1))
344 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
345 GFS_DYNAMIC
, chunk_size
);
346 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
347 gomp_work_share_init_done ();
350 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
352 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
354 gomp_ordered_first ();
355 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
361 gomp_loop_ull_ordered_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
362 gomp_ull incr
, gomp_ull chunk_size
,
363 gomp_ull
*istart
, gomp_ull
*iend
)
365 struct gomp_thread
*thr
= gomp_thread ();
368 if (gomp_work_share_start (1))
370 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
371 GFS_GUIDED
, chunk_size
);
372 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
373 gomp_work_share_init_done ();
376 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
378 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
380 gomp_ordered_first ();
381 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
387 GOMP_loop_ull_ordered_runtime_start (bool up
, gomp_ull start
, gomp_ull end
,
388 gomp_ull incr
, gomp_ull
*istart
,
391 struct gomp_task_icv
*icv
= gomp_icv (false);
392 switch (icv
->run_sched_var
& ~GFS_MONOTONIC
)
395 return gomp_loop_ull_ordered_static_start (up
, start
, end
, incr
,
396 icv
->run_sched_chunk_size
,
399 return gomp_loop_ull_ordered_dynamic_start (up
, start
, end
, incr
,
400 icv
->run_sched_chunk_size
,
403 return gomp_loop_ull_ordered_guided_start (up
, start
, end
, incr
,
404 icv
->run_sched_chunk_size
,
407 /* For now map to schedule(static), later on we could play with feedback
409 return gomp_loop_ull_ordered_static_start (up
, start
, end
, incr
,
417 GOMP_loop_ull_ordered_start (bool up
, gomp_ull start
, gomp_ull end
,
418 gomp_ull incr
, long sched
, gomp_ull chunk_size
,
419 gomp_ull
*istart
, gomp_ull
*iend
,
420 uintptr_t *reductions
, void **mem
)
422 struct gomp_thread
*thr
= gomp_thread ();
426 thr
->ts
.static_trip
= 0;
428 gomp_workshare_taskgroup_start ();
430 ordered
+= (uintptr_t) *mem
;
431 if (gomp_work_share_start (ordered
))
433 sched
= gomp_adjust_sched (sched
, &chunk_size
);
434 gomp_loop_ull_init (thr
->ts
.work_share
, up
, start
, end
, incr
,
438 GOMP_taskgroup_reduction_register (reductions
);
439 thr
->task
->taskgroup
->workshare
= true;
440 thr
->ts
.work_share
->task_reductions
= reductions
;
442 if (sched
== GFS_STATIC
)
443 gomp_ordered_static_init ();
445 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
446 gomp_work_share_init_done ();
452 uintptr_t *first_reductions
= thr
->ts
.work_share
->task_reductions
;
453 gomp_workshare_task_reduction_register (reductions
,
456 sched
= thr
->ts
.work_share
->sched
;
457 if (sched
!= GFS_STATIC
)
458 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
464 = (uintptr_t) (thr
->ts
.work_share
->ordered_team_ids
465 + (thr
->ts
.team
? thr
->ts
.team
->nthreads
: 1));
466 p
+= __alignof__ (long long) - 1;
467 p
&= ~(__alignof__ (long long) - 1);
475 return !gomp_iter_ull_static_next (istart
, iend
);
477 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
480 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
487 gomp_ordered_first ();
488 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
492 /* The *_doacross_*_start routines are similar. The only difference is that
493 this work-share construct is initialized to expect an ORDERED(N) - DOACROSS
494 section, and the worksharing loop iterates always from 0 to COUNTS[0] - 1
495 and other COUNTS array elements tell the library number of iterations
496 in the ordered inner loops. */
499 gomp_loop_ull_doacross_static_start (unsigned ncounts
, gomp_ull
*counts
,
500 gomp_ull chunk_size
, gomp_ull
*istart
,
503 struct gomp_thread
*thr
= gomp_thread ();
505 thr
->ts
.static_trip
= 0;
506 if (gomp_work_share_start (0))
508 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
509 GFS_STATIC
, chunk_size
);
510 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, 0);
511 gomp_work_share_init_done ();
514 return !gomp_iter_ull_static_next (istart
, iend
);
518 gomp_loop_ull_doacross_dynamic_start (unsigned ncounts
, gomp_ull
*counts
,
519 gomp_ull chunk_size
, gomp_ull
*istart
,
522 struct gomp_thread
*thr
= gomp_thread ();
525 if (gomp_work_share_start (0))
527 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
528 GFS_DYNAMIC
, chunk_size
);
529 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, 0);
530 gomp_work_share_init_done ();
533 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
534 ret
= gomp_iter_ull_dynamic_next (istart
, iend
);
536 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
537 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
538 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
545 gomp_loop_ull_doacross_guided_start (unsigned ncounts
, gomp_ull
*counts
,
546 gomp_ull chunk_size
, gomp_ull
*istart
,
549 struct gomp_thread
*thr
= gomp_thread ();
552 if (gomp_work_share_start (0))
554 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
555 GFS_GUIDED
, chunk_size
);
556 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, 0);
557 gomp_work_share_init_done ();
560 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
561 ret
= gomp_iter_ull_guided_next (istart
, iend
);
563 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
564 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
565 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
572 GOMP_loop_ull_doacross_runtime_start (unsigned ncounts
, gomp_ull
*counts
,
573 gomp_ull
*istart
, gomp_ull
*iend
)
575 struct gomp_task_icv
*icv
= gomp_icv (false);
576 switch (icv
->run_sched_var
& ~GFS_MONOTONIC
)
579 return gomp_loop_ull_doacross_static_start (ncounts
, counts
,
580 icv
->run_sched_chunk_size
,
583 return gomp_loop_ull_doacross_dynamic_start (ncounts
, counts
,
584 icv
->run_sched_chunk_size
,
587 return gomp_loop_ull_doacross_guided_start (ncounts
, counts
,
588 icv
->run_sched_chunk_size
,
591 /* For now map to schedule(static), later on we could play with feedback
593 return gomp_loop_ull_doacross_static_start (ncounts
, counts
,
601 GOMP_loop_ull_doacross_start (unsigned ncounts
, gomp_ull
*counts
,
602 long sched
, gomp_ull chunk_size
,
603 gomp_ull
*istart
, gomp_ull
*iend
,
604 uintptr_t *reductions
, void **mem
)
606 struct gomp_thread
*thr
= gomp_thread ();
608 thr
->ts
.static_trip
= 0;
610 gomp_workshare_taskgroup_start ();
611 if (gomp_work_share_start (0))
615 extra
= (uintptr_t) *mem
;
616 sched
= gomp_adjust_sched (sched
, &chunk_size
);
617 gomp_loop_ull_init (thr
->ts
.work_share
, true, 0, counts
[0], 1,
619 gomp_doacross_ull_init (ncounts
, counts
, chunk_size
, extra
);
622 GOMP_taskgroup_reduction_register (reductions
);
623 thr
->task
->taskgroup
->workshare
= true;
624 thr
->ts
.work_share
->task_reductions
= reductions
;
626 gomp_work_share_init_done ();
632 uintptr_t *first_reductions
= thr
->ts
.work_share
->task_reductions
;
633 gomp_workshare_task_reduction_register (reductions
,
636 sched
= thr
->ts
.work_share
->sched
;
640 *mem
= thr
->ts
.work_share
->doacross
->extra
;
642 return ialias_call (GOMP_loop_ull_runtime_next
) (istart
, iend
);
645 /* The *_next routines are called when the thread completes processing of
646 the iteration block currently assigned to it. If the work-share
647 construct is bound directly to a parallel construct, then the iteration
648 bounds may have been set up before the parallel. In which case, this
649 may be the first iteration for the thread.
651 Returns true if there is work remaining to be performed; *ISTART and
652 *IEND are filled with a new iteration block. Returns false if all work
653 has been assigned. */
656 gomp_loop_ull_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
658 return !gomp_iter_ull_static_next (istart
, iend
);
662 gomp_loop_ull_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
666 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
667 ret
= gomp_iter_ull_dynamic_next (istart
, iend
);
669 struct gomp_thread
*thr
= gomp_thread ();
670 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
671 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
672 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
679 gomp_loop_ull_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
683 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
684 ret
= gomp_iter_ull_guided_next (istart
, iend
);
686 struct gomp_thread
*thr
= gomp_thread ();
687 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
688 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
689 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
696 GOMP_loop_ull_runtime_next (gomp_ull
*istart
, gomp_ull
*iend
)
698 struct gomp_thread
*thr
= gomp_thread ();
700 switch (thr
->ts
.work_share
->sched
)
704 return gomp_loop_ull_static_next (istart
, iend
);
706 return gomp_loop_ull_dynamic_next (istart
, iend
);
708 return gomp_loop_ull_guided_next (istart
, iend
);
714 /* The *_ordered_*_next routines are called when the thread completes
715 processing of the iteration block currently assigned to it.
717 Returns true if there is work remaining to be performed; *ISTART and
718 *IEND are filled with a new iteration block. Returns false if all work
719 has been assigned. */
722 gomp_loop_ull_ordered_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
724 struct gomp_thread
*thr
= gomp_thread ();
727 gomp_ordered_sync ();
728 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
729 test
= gomp_iter_ull_static_next (istart
, iend
);
731 gomp_ordered_static_next ();
732 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
738 gomp_loop_ull_ordered_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
740 struct gomp_thread
*thr
= gomp_thread ();
743 gomp_ordered_sync ();
744 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
745 ret
= gomp_iter_ull_dynamic_next_locked (istart
, iend
);
747 gomp_ordered_next ();
749 gomp_ordered_last ();
750 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
756 gomp_loop_ull_ordered_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
758 struct gomp_thread
*thr
= gomp_thread ();
761 gomp_ordered_sync ();
762 gomp_mutex_lock (&thr
->ts
.work_share
->lock
);
763 ret
= gomp_iter_ull_guided_next_locked (istart
, iend
);
765 gomp_ordered_next ();
767 gomp_ordered_last ();
768 gomp_mutex_unlock (&thr
->ts
.work_share
->lock
);
774 GOMP_loop_ull_ordered_runtime_next (gomp_ull
*istart
, gomp_ull
*iend
)
776 struct gomp_thread
*thr
= gomp_thread ();
778 switch (thr
->ts
.work_share
->sched
)
782 return gomp_loop_ull_ordered_static_next (istart
, iend
);
784 return gomp_loop_ull_ordered_dynamic_next (istart
, iend
);
786 return gomp_loop_ull_ordered_guided_next (istart
, iend
);
792 /* We use static functions above so that we're sure that the "runtime"
793 function can defer to the proper routine without interposition. We
794 export the static function with a strong alias when possible, or with
795 a wrapper function otherwise. */
797 #ifdef HAVE_ATTRIBUTE_ALIAS
798 extern __typeof(gomp_loop_ull_static_start
) GOMP_loop_ull_static_start
799 __attribute__((alias ("gomp_loop_ull_static_start")));
800 extern __typeof(gomp_loop_ull_dynamic_start
) GOMP_loop_ull_dynamic_start
801 __attribute__((alias ("gomp_loop_ull_dynamic_start")));
802 extern __typeof(gomp_loop_ull_guided_start
) GOMP_loop_ull_guided_start
803 __attribute__((alias ("gomp_loop_ull_guided_start")));
804 extern __typeof(gomp_loop_ull_dynamic_start
) GOMP_loop_ull_nonmonotonic_dynamic_start
805 __attribute__((alias ("gomp_loop_ull_dynamic_start")));
806 extern __typeof(gomp_loop_ull_guided_start
) GOMP_loop_ull_nonmonotonic_guided_start
807 __attribute__((alias ("gomp_loop_ull_guided_start")));
808 extern __typeof(GOMP_loop_ull_runtime_start
) GOMP_loop_ull_nonmonotonic_runtime_start
809 __attribute__((alias ("GOMP_loop_ull_runtime_start")));
810 extern __typeof(GOMP_loop_ull_runtime_start
) GOMP_loop_ull_maybe_nonmonotonic_runtime_start
811 __attribute__((alias ("GOMP_loop_ull_runtime_start")));
813 extern __typeof(gomp_loop_ull_ordered_static_start
) GOMP_loop_ull_ordered_static_start
814 __attribute__((alias ("gomp_loop_ull_ordered_static_start")));
815 extern __typeof(gomp_loop_ull_ordered_dynamic_start
) GOMP_loop_ull_ordered_dynamic_start
816 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_start")));
817 extern __typeof(gomp_loop_ull_ordered_guided_start
) GOMP_loop_ull_ordered_guided_start
818 __attribute__((alias ("gomp_loop_ull_ordered_guided_start")));
820 extern __typeof(gomp_loop_ull_doacross_static_start
) GOMP_loop_ull_doacross_static_start
821 __attribute__((alias ("gomp_loop_ull_doacross_static_start")));
822 extern __typeof(gomp_loop_ull_doacross_dynamic_start
) GOMP_loop_ull_doacross_dynamic_start
823 __attribute__((alias ("gomp_loop_ull_doacross_dynamic_start")));
824 extern __typeof(gomp_loop_ull_doacross_guided_start
) GOMP_loop_ull_doacross_guided_start
825 __attribute__((alias ("gomp_loop_ull_doacross_guided_start")));
827 extern __typeof(gomp_loop_ull_static_next
) GOMP_loop_ull_static_next
828 __attribute__((alias ("gomp_loop_ull_static_next")));
829 extern __typeof(gomp_loop_ull_dynamic_next
) GOMP_loop_ull_dynamic_next
830 __attribute__((alias ("gomp_loop_ull_dynamic_next")));
831 extern __typeof(gomp_loop_ull_guided_next
) GOMP_loop_ull_guided_next
832 __attribute__((alias ("gomp_loop_ull_guided_next")));
833 extern __typeof(gomp_loop_ull_dynamic_next
) GOMP_loop_ull_nonmonotonic_dynamic_next
834 __attribute__((alias ("gomp_loop_ull_dynamic_next")));
835 extern __typeof(gomp_loop_ull_guided_next
) GOMP_loop_ull_nonmonotonic_guided_next
836 __attribute__((alias ("gomp_loop_ull_guided_next")));
837 extern __typeof(GOMP_loop_ull_runtime_next
) GOMP_loop_ull_nonmonotonic_runtime_next
838 __attribute__((alias ("GOMP_loop_ull_runtime_next")));
839 extern __typeof(GOMP_loop_ull_runtime_next
) GOMP_loop_ull_maybe_nonmonotonic_runtime_next
840 __attribute__((alias ("GOMP_loop_ull_runtime_next")));
842 extern __typeof(gomp_loop_ull_ordered_static_next
) GOMP_loop_ull_ordered_static_next
843 __attribute__((alias ("gomp_loop_ull_ordered_static_next")));
844 extern __typeof(gomp_loop_ull_ordered_dynamic_next
) GOMP_loop_ull_ordered_dynamic_next
845 __attribute__((alias ("gomp_loop_ull_ordered_dynamic_next")));
846 extern __typeof(gomp_loop_ull_ordered_guided_next
) GOMP_loop_ull_ordered_guided_next
847 __attribute__((alias ("gomp_loop_ull_ordered_guided_next")));
850 GOMP_loop_ull_static_start (bool up
, gomp_ull start
, gomp_ull end
,
851 gomp_ull incr
, gomp_ull chunk_size
,
852 gomp_ull
*istart
, gomp_ull
*iend
)
854 return gomp_loop_ull_static_start (up
, start
, end
, incr
, chunk_size
, istart
,
859 GOMP_loop_ull_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
860 gomp_ull incr
, gomp_ull chunk_size
,
861 gomp_ull
*istart
, gomp_ull
*iend
)
863 return gomp_loop_ull_dynamic_start (up
, start
, end
, incr
, chunk_size
, istart
,
868 GOMP_loop_ull_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
869 gomp_ull incr
, gomp_ull chunk_size
,
870 gomp_ull
*istart
, gomp_ull
*iend
)
872 return gomp_loop_ull_guided_start (up
, start
, end
, incr
, chunk_size
, istart
,
877 GOMP_loop_ull_nonmonotonic_dynamic_start (bool up
, gomp_ull start
,
878 gomp_ull end
, gomp_ull incr
,
880 gomp_ull
*istart
, gomp_ull
*iend
)
882 return gomp_loop_ull_dynamic_start (up
, start
, end
, incr
, chunk_size
, istart
,
887 GOMP_loop_ull_nonmonotonic_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
888 gomp_ull incr
, gomp_ull chunk_size
,
889 gomp_ull
*istart
, gomp_ull
*iend
)
891 return gomp_loop_ull_guided_start (up
, start
, end
, incr
, chunk_size
, istart
,
896 GOMP_loop_ull_nonmonotonic_runtime_start (bool up
, gomp_ull start
,
897 gomp_ull end
, gomp_ull incr
,
898 gomp_ull
*istart
, gomp_ull
*iend
)
900 return GOMP_loop_ull_runtime_start (up
, start
, end
, incr
, istart
, iend
);
904 GOMP_loop_ull_maybe_nonmonotonic_runtime_start (bool up
, gomp_ull start
,
905 gomp_ull end
, gomp_ull incr
,
909 return GOMP_loop_ull_runtime_start (up
, start
, end
, incr
, istart
, iend
);
913 GOMP_loop_ull_ordered_static_start (bool up
, gomp_ull start
, gomp_ull end
,
914 gomp_ull incr
, gomp_ull chunk_size
,
915 gomp_ull
*istart
, gomp_ull
*iend
)
917 return gomp_loop_ull_ordered_static_start (up
, start
, end
, incr
, chunk_size
,
922 GOMP_loop_ull_ordered_dynamic_start (bool up
, gomp_ull start
, gomp_ull end
,
923 gomp_ull incr
, gomp_ull chunk_size
,
924 gomp_ull
*istart
, gomp_ull
*iend
)
926 return gomp_loop_ull_ordered_dynamic_start (up
, start
, end
, incr
, chunk_size
,
931 GOMP_loop_ull_ordered_guided_start (bool up
, gomp_ull start
, gomp_ull end
,
932 gomp_ull incr
, gomp_ull chunk_size
,
933 gomp_ull
*istart
, gomp_ull
*iend
)
935 return gomp_loop_ull_ordered_guided_start (up
, start
, end
, incr
, chunk_size
,
940 GOMP_loop_ull_doacross_static_start (unsigned ncounts
, gomp_ull
*counts
,
941 gomp_ull chunk_size
, gomp_ull
*istart
,
944 return gomp_loop_ull_doacross_static_start (ncounts
, counts
, chunk_size
,
949 GOMP_loop_ull_doacross_dynamic_start (unsigned ncounts
, gomp_ull
*counts
,
950 gomp_ull chunk_size
, gomp_ull
*istart
,
953 return gomp_loop_ull_doacross_dynamic_start (ncounts
, counts
, chunk_size
,
958 GOMP_loop_ull_doacross_guided_start (unsigned ncounts
, gomp_ull
*counts
,
959 gomp_ull chunk_size
, gomp_ull
*istart
,
962 return gomp_loop_ull_doacross_guided_start (ncounts
, counts
, chunk_size
,
967 GOMP_loop_ull_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
969 return gomp_loop_ull_static_next (istart
, iend
);
973 GOMP_loop_ull_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
975 return gomp_loop_ull_dynamic_next (istart
, iend
);
979 GOMP_loop_ull_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
981 return gomp_loop_ull_guided_next (istart
, iend
);
985 GOMP_loop_ull_nonmonotonic_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
987 return gomp_loop_ull_dynamic_next (istart
, iend
);
991 GOMP_loop_ull_nonmonotonic_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
993 return gomp_loop_ull_guided_next (istart
, iend
);
997 GOMP_loop_ull_nonmonotonic_runtime_next (gomp_ull
*istart
, gomp_ull
*iend
)
999 return GOMP_loop_ull_runtime_next (istart
, iend
);
1003 GOMP_loop_ull_maybe_nonmonotonic_runtime_next (gomp_ull
*istart
,
1006 return GOMP_loop_ull_runtime_next (istart
, iend
);
1010 GOMP_loop_ull_ordered_static_next (gomp_ull
*istart
, gomp_ull
*iend
)
1012 return gomp_loop_ull_ordered_static_next (istart
, iend
);
1016 GOMP_loop_ull_ordered_dynamic_next (gomp_ull
*istart
, gomp_ull
*iend
)
1018 return gomp_loop_ull_ordered_dynamic_next (istart
, iend
);
1022 GOMP_loop_ull_ordered_guided_next (gomp_ull
*istart
, gomp_ull
*iend
)
1024 return gomp_loop_ull_ordered_guided_next (istart
, iend
);