1345153Sdim/*
2345153Sdim * kmp_sched.cpp -- static scheduling -- iteration initialization
3345153Sdim */
4345153Sdim
5345153Sdim//===----------------------------------------------------------------------===//
6345153Sdim//
7353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8353358Sdim// See https://llvm.org/LICENSE.txt for license information.
9353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10345153Sdim//
11345153Sdim//===----------------------------------------------------------------------===//
12345153Sdim
13345153Sdim/* Static scheduling initialization.
14345153Sdim
15345153Sdim  NOTE: team->t.t_nproc is a constant inside of any dispatch loop, however
16345153Sdim        it may change values between parallel regions.  __kmp_max_nth
17345153Sdim        is the largest value __kmp_nth may take, 1 is the smallest. */
18345153Sdim
19345153Sdim#include "kmp.h"
20345153Sdim#include "kmp_error.h"
21345153Sdim#include "kmp_i18n.h"
22345153Sdim#include "kmp_itt.h"
23345153Sdim#include "kmp_stats.h"
24345153Sdim#include "kmp_str.h"
25345153Sdim
26345153Sdim#if OMPT_SUPPORT
27345153Sdim#include "ompt-specific.h"
28345153Sdim#endif
29345153Sdim
30345153Sdim#ifdef KMP_DEBUG
31345153Sdim//-------------------------------------------------------------------------
32345153Sdim// template for debug prints specification ( d, u, lld, llu )
33345153Sdimchar const *traits_t<int>::spec = "d";
34345153Sdimchar const *traits_t<unsigned int>::spec = "u";
35345153Sdimchar const *traits_t<long long>::spec = "lld";
36345153Sdimchar const *traits_t<unsigned long long>::spec = "llu";
37345153Sdimchar const *traits_t<long>::spec = "ld";
38345153Sdim//-------------------------------------------------------------------------
39345153Sdim#endif
40345153Sdim
41353358Sdim#if KMP_STATS_ENABLED
42353358Sdim#define KMP_STATS_LOOP_END(stat)                                               \
43353358Sdim  {                                                                            \
44353358Sdim    kmp_int64 t;                                                               \
45353358Sdim    kmp_int64 u = (kmp_int64)(*pupper);                                        \
46353358Sdim    kmp_int64 l = (kmp_int64)(*plower);                                        \
47353358Sdim    kmp_int64 i = (kmp_int64)incr;                                             \
48353358Sdim    if (i == 1) {                                                              \
49353358Sdim      t = u - l + 1;                                                           \
50353358Sdim    } else if (i == -1) {                                                      \
51353358Sdim      t = l - u + 1;                                                           \
52353358Sdim    } else if (i > 0) {                                                        \
53353358Sdim      t = (u - l) / i + 1;                                                     \
54353358Sdim    } else {                                                                   \
55353358Sdim      t = (l - u) / (-i) + 1;                                                  \
56353358Sdim    }                                                                          \
57353358Sdim    KMP_COUNT_VALUE(stat, t);                                                  \
58353358Sdim    KMP_POP_PARTITIONED_TIMER();                                               \
59353358Sdim  }
60353358Sdim#else
61353358Sdim#define KMP_STATS_LOOP_END(stat) /* Nothing */
62353358Sdim#endif
63353358Sdim
64345153Sdimtemplate <typename T>
65345153Sdimstatic void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid,
66345153Sdim                                  kmp_int32 schedtype, kmp_int32 *plastiter,
67345153Sdim                                  T *plower, T *pupper,
68345153Sdim                                  typename traits_t<T>::signed_t *pstride,
69345153Sdim                                  typename traits_t<T>::signed_t incr,
70345153Sdim                                  typename traits_t<T>::signed_t chunk
71345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
72345153Sdim                                  ,
73345153Sdim                                  void *codeptr
74345153Sdim#endif
75345153Sdim                                  ) {
76345153Sdim  KMP_COUNT_BLOCK(OMP_LOOP_STATIC);
77345153Sdim  KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static);
78345153Sdim  KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static_scheduling);
79345153Sdim
80345153Sdim  typedef typename traits_t<T>::unsigned_t UT;
81345153Sdim  typedef typename traits_t<T>::signed_t ST;
82345153Sdim  /*  this all has to be changed back to TID and such.. */
83345153Sdim  kmp_int32 gtid = global_tid;
84345153Sdim  kmp_uint32 tid;
85345153Sdim  kmp_uint32 nth;
86345153Sdim  UT trip_count;
87345153Sdim  kmp_team_t *team;
88345153Sdim  kmp_info_t *th = __kmp_threads[gtid];
89345153Sdim
90345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
91345153Sdim  ompt_team_info_t *team_info = NULL;
92345153Sdim  ompt_task_info_t *task_info = NULL;
93345153Sdim  ompt_work_t ompt_work_type = ompt_work_loop;
94345153Sdim
95345153Sdim  static kmp_int8 warn = 0;
96345153Sdim
97345153Sdim  if (ompt_enabled.ompt_callback_work) {
98345153Sdim    // Only fully initialize variables needed by OMPT if OMPT is enabled.
99345153Sdim    team_info = __ompt_get_teaminfo(0, NULL);
100345153Sdim    task_info = __ompt_get_task_info_object(0);
101345153Sdim    // Determine workshare type
102345153Sdim    if (loc != NULL) {
103345153Sdim      if ((loc->flags & KMP_IDENT_WORK_LOOP) != 0) {
104345153Sdim        ompt_work_type = ompt_work_loop;
105345153Sdim      } else if ((loc->flags & KMP_IDENT_WORK_SECTIONS) != 0) {
106345153Sdim        ompt_work_type = ompt_work_sections;
107345153Sdim      } else if ((loc->flags & KMP_IDENT_WORK_DISTRIBUTE) != 0) {
108345153Sdim        ompt_work_type = ompt_work_distribute;
109345153Sdim      } else {
110345153Sdim        kmp_int8 bool_res =
111345153Sdim            KMP_COMPARE_AND_STORE_ACQ8(&warn, (kmp_int8)0, (kmp_int8)1);
112345153Sdim        if (bool_res)
113345153Sdim          KMP_WARNING(OmptOutdatedWorkshare);
114345153Sdim      }
115345153Sdim      KMP_DEBUG_ASSERT(ompt_work_type);
116345153Sdim    }
117345153Sdim  }
118345153Sdim#endif
119345153Sdim
120345153Sdim  KMP_DEBUG_ASSERT(plastiter && plower && pupper && pstride);
121345153Sdim  KE_TRACE(10, ("__kmpc_for_static_init called (%d)\n", global_tid));
122345153Sdim#ifdef KMP_DEBUG
123345153Sdim  {
124345153Sdim    char *buff;
125345153Sdim    // create format specifiers before the debug output
126345153Sdim    buff = __kmp_str_format(
127345153Sdim        "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s,"
128345153Sdim        " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
129345153Sdim        traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
130345153Sdim        traits_t<ST>::spec, traits_t<ST>::spec, traits_t<T>::spec);
131345153Sdim    KD_TRACE(100, (buff, global_tid, schedtype, *plastiter, *plower, *pupper,
132345153Sdim                   *pstride, incr, chunk));
133345153Sdim    __kmp_str_free(&buff);
134345153Sdim  }
135345153Sdim#endif
136345153Sdim
137345153Sdim  if (__kmp_env_consistency_check) {
138345153Sdim    __kmp_push_workshare(global_tid, ct_pdo, loc);
139345153Sdim    if (incr == 0) {
140345153Sdim      __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
141345153Sdim                            loc);
142345153Sdim    }
143345153Sdim  }
144345153Sdim  /* special handling for zero-trip loops */
145345153Sdim  if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
146345153Sdim    if (plastiter != NULL)
147345153Sdim      *plastiter = FALSE;
148345153Sdim    /* leave pupper and plower set to entire iteration space */
149345153Sdim    *pstride = incr; /* value should never be used */
150345153Sdim// *plower = *pupper - incr;
151345153Sdim// let compiler bypass the illegal loop (like for(i=1;i<10;i--))
152345153Sdim// THE LINE COMMENTED ABOVE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE
153345153Sdim// ON A ZERO-TRIP LOOP (lower=1, upper=0,stride=1) - JPH June 23, 2009.
154345153Sdim#ifdef KMP_DEBUG
155345153Sdim    {
156345153Sdim      char *buff;
157345153Sdim      // create format specifiers before the debug output
158345153Sdim      buff = __kmp_str_format("__kmpc_for_static_init:(ZERO TRIP) liter=%%d "
159345153Sdim                              "lower=%%%s upper=%%%s stride = %%%s "
160345153Sdim                              "signed?<%s>, loc = %%s\n",
161345153Sdim                              traits_t<T>::spec, traits_t<T>::spec,
162345153Sdim                              traits_t<ST>::spec, traits_t<T>::spec);
163345153Sdim      KD_TRACE(100,
164345153Sdim               (buff, *plastiter, *plower, *pupper, *pstride, loc->psource));
165345153Sdim      __kmp_str_free(&buff);
166345153Sdim    }
167345153Sdim#endif
168345153Sdim    KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
169345153Sdim
170345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
171345153Sdim    if (ompt_enabled.ompt_callback_work) {
172345153Sdim      ompt_callbacks.ompt_callback(ompt_callback_work)(
173345153Sdim          ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
174345153Sdim          &(task_info->task_data), 0, codeptr);
175345153Sdim    }
176345153Sdim#endif
177353358Sdim    KMP_STATS_LOOP_END(OMP_loop_static_iterations);
178345153Sdim    return;
179345153Sdim  }
180345153Sdim
181345153Sdim  // Although there are schedule enumerations above kmp_ord_upper which are not
182345153Sdim  // schedules for "distribute", the only ones which are useful are dynamic, so
183345153Sdim  // cannot be seen here, since this codepath is only executed for static
184345153Sdim  // schedules.
185345153Sdim  if (schedtype > kmp_ord_upper) {
186345153Sdim    // we are in DISTRIBUTE construct
187345153Sdim    schedtype += kmp_sch_static -
188345153Sdim                 kmp_distribute_static; // AC: convert to usual schedule type
189345153Sdim    tid = th->th.th_team->t.t_master_tid;
190345153Sdim    team = th->th.th_team->t.t_parent;
191353358Sdim  } else {
192345153Sdim    tid = __kmp_tid_from_gtid(global_tid);
193345153Sdim    team = th->th.th_team;
194345153Sdim  }
195345153Sdim
196345153Sdim  /* determine if "for" loop is an active worksharing construct */
197345153Sdim  if (team->t.t_serialized) {
198345153Sdim    /* serialized parallel, each thread executes whole iteration space */
199345153Sdim    if (plastiter != NULL)
200345153Sdim      *plastiter = TRUE;
201345153Sdim    /* leave pupper and plower set to entire iteration space */
202345153Sdim    *pstride =
203345153Sdim        (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
204345153Sdim
205345153Sdim#ifdef KMP_DEBUG
206345153Sdim    {
207345153Sdim      char *buff;
208345153Sdim      // create format specifiers before the debug output
209345153Sdim      buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
210345153Sdim                              "lower=%%%s upper=%%%s stride = %%%s\n",
211345153Sdim                              traits_t<T>::spec, traits_t<T>::spec,
212345153Sdim                              traits_t<ST>::spec);
213345153Sdim      KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
214345153Sdim      __kmp_str_free(&buff);
215345153Sdim    }
216345153Sdim#endif
217345153Sdim    KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
218345153Sdim
219345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
220345153Sdim    if (ompt_enabled.ompt_callback_work) {
221345153Sdim      ompt_callbacks.ompt_callback(ompt_callback_work)(
222345153Sdim          ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
223345153Sdim          &(task_info->task_data), *pstride, codeptr);
224345153Sdim    }
225345153Sdim#endif
226353358Sdim    KMP_STATS_LOOP_END(OMP_loop_static_iterations);
227345153Sdim    return;
228345153Sdim  }
229345153Sdim  nth = team->t.t_nproc;
230345153Sdim  if (nth == 1) {
231345153Sdim    if (plastiter != NULL)
232345153Sdim      *plastiter = TRUE;
233345153Sdim    *pstride =
234345153Sdim        (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
235345153Sdim#ifdef KMP_DEBUG
236345153Sdim    {
237345153Sdim      char *buff;
238345153Sdim      // create format specifiers before the debug output
239345153Sdim      buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
240345153Sdim                              "lower=%%%s upper=%%%s stride = %%%s\n",
241345153Sdim                              traits_t<T>::spec, traits_t<T>::spec,
242345153Sdim                              traits_t<ST>::spec);
243345153Sdim      KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
244345153Sdim      __kmp_str_free(&buff);
245345153Sdim    }
246345153Sdim#endif
247345153Sdim    KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
248345153Sdim
249345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
250345153Sdim    if (ompt_enabled.ompt_callback_work) {
251345153Sdim      ompt_callbacks.ompt_callback(ompt_callback_work)(
252345153Sdim          ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
253345153Sdim          &(task_info->task_data), *pstride, codeptr);
254345153Sdim    }
255345153Sdim#endif
256353358Sdim    KMP_STATS_LOOP_END(OMP_loop_static_iterations);
257345153Sdim    return;
258345153Sdim  }
259345153Sdim
260345153Sdim  /* compute trip count */
261345153Sdim  if (incr == 1) {
262345153Sdim    trip_count = *pupper - *plower + 1;
263345153Sdim  } else if (incr == -1) {
264345153Sdim    trip_count = *plower - *pupper + 1;
265345153Sdim  } else if (incr > 0) {
266345153Sdim    // upper-lower can exceed the limit of signed type
267345153Sdim    trip_count = (UT)(*pupper - *plower) / incr + 1;
268345153Sdim  } else {
269345153Sdim    trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
270345153Sdim  }
271345153Sdim
272353358Sdim#if KMP_STATS_ENABLED
273353358Sdim  if (KMP_MASTER_GTID(gtid)) {
274353358Sdim    KMP_COUNT_VALUE(OMP_loop_static_total_iterations, trip_count);
275353358Sdim  }
276353358Sdim#endif
277353358Sdim
278345153Sdim  if (__kmp_env_consistency_check) {
279345153Sdim    /* tripcount overflow? */
280345153Sdim    if (trip_count == 0 && *pupper != *plower) {
281345153Sdim      __kmp_error_construct(kmp_i18n_msg_CnsIterationRangeTooLarge, ct_pdo,
282345153Sdim                            loc);
283345153Sdim    }
284345153Sdim  }
285345153Sdim
286345153Sdim  /* compute remaining parameters */
287345153Sdim  switch (schedtype) {
288345153Sdim  case kmp_sch_static: {
289345153Sdim    if (trip_count < nth) {
290345153Sdim      KMP_DEBUG_ASSERT(
291345153Sdim          __kmp_static == kmp_sch_static_greedy ||
292345153Sdim          __kmp_static ==
293345153Sdim              kmp_sch_static_balanced); // Unknown static scheduling type.
294345153Sdim      if (tid < trip_count) {
295345153Sdim        *pupper = *plower = *plower + tid * incr;
296345153Sdim      } else {
297345153Sdim        *plower = *pupper + incr;
298345153Sdim      }
299345153Sdim      if (plastiter != NULL)
300345153Sdim        *plastiter = (tid == trip_count - 1);
301345153Sdim    } else {
302345153Sdim      if (__kmp_static == kmp_sch_static_balanced) {
303345153Sdim        UT small_chunk = trip_count / nth;
304345153Sdim        UT extras = trip_count % nth;
305345153Sdim        *plower += incr * (tid * small_chunk + (tid < extras ? tid : extras));
306345153Sdim        *pupper = *plower + small_chunk * incr - (tid < extras ? 0 : incr);
307345153Sdim        if (plastiter != NULL)
308345153Sdim          *plastiter = (tid == nth - 1);
309345153Sdim      } else {
310345153Sdim        T big_chunk_inc_count =
311345153Sdim            (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
312345153Sdim        T old_upper = *pupper;
313345153Sdim
314345153Sdim        KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
315345153Sdim        // Unknown static scheduling type.
316345153Sdim
317345153Sdim        *plower += tid * big_chunk_inc_count;
318345153Sdim        *pupper = *plower + big_chunk_inc_count - incr;
319345153Sdim        if (incr > 0) {
320345153Sdim          if (*pupper < *plower)
321345153Sdim            *pupper = traits_t<T>::max_value;
322345153Sdim          if (plastiter != NULL)
323345153Sdim            *plastiter = *plower <= old_upper && *pupper > old_upper - incr;
324345153Sdim          if (*pupper > old_upper)
325345153Sdim            *pupper = old_upper; // tracker C73258
326345153Sdim        } else {
327345153Sdim          if (*pupper > *plower)
328345153Sdim            *pupper = traits_t<T>::min_value;
329345153Sdim          if (plastiter != NULL)
330345153Sdim            *plastiter = *plower >= old_upper && *pupper < old_upper - incr;
331345153Sdim          if (*pupper < old_upper)
332345153Sdim            *pupper = old_upper; // tracker C73258
333345153Sdim        }
334345153Sdim      }
335345153Sdim    }
336345153Sdim    *pstride = trip_count;
337345153Sdim    break;
338345153Sdim  }
339345153Sdim  case kmp_sch_static_chunked: {
340345153Sdim    ST span;
341345153Sdim    if (chunk < 1) {
342345153Sdim      chunk = 1;
343345153Sdim    }
344345153Sdim    span = chunk * incr;
345345153Sdim    *pstride = span * nth;
346345153Sdim    *plower = *plower + (span * tid);
347345153Sdim    *pupper = *plower + span - incr;
348345153Sdim    if (plastiter != NULL)
349345153Sdim      *plastiter = (tid == ((trip_count - 1) / (UT)chunk) % nth);
350345153Sdim    break;
351345153Sdim  }
352345153Sdim  case kmp_sch_static_balanced_chunked: {
353345153Sdim    T old_upper = *pupper;
354345153Sdim    // round up to make sure the chunk is enough to cover all iterations
355345153Sdim    UT span = (trip_count + nth - 1) / nth;
356345153Sdim
357345153Sdim    // perform chunk adjustment
358345153Sdim    chunk = (span + chunk - 1) & ~(chunk - 1);
359345153Sdim
360345153Sdim    span = chunk * incr;
361345153Sdim    *plower = *plower + (span * tid);
362345153Sdim    *pupper = *plower + span - incr;
363345153Sdim    if (incr > 0) {
364345153Sdim      if (*pupper > old_upper)
365345153Sdim        *pupper = old_upper;
366345153Sdim    } else if (*pupper < old_upper)
367345153Sdim      *pupper = old_upper;
368345153Sdim
369345153Sdim    if (plastiter != NULL)
370345153Sdim      *plastiter = (tid == ((trip_count - 1) / (UT)chunk));
371345153Sdim    break;
372345153Sdim  }
373345153Sdim  default:
374345153Sdim    KMP_ASSERT2(0, "__kmpc_for_static_init: unknown scheduling type");
375345153Sdim    break;
376345153Sdim  }
377345153Sdim
378345153Sdim#if USE_ITT_BUILD
379345153Sdim  // Report loop metadata
380345153Sdim  if (KMP_MASTER_TID(tid) && __itt_metadata_add_ptr &&
381353358Sdim      __kmp_forkjoin_frames_mode == 3 && th->th.th_teams_microtask == NULL &&
382345153Sdim      team->t.t_active_level == 1) {
383345153Sdim    kmp_uint64 cur_chunk = chunk;
384345153Sdim    // Calculate chunk in case it was not specified; it is specified for
385345153Sdim    // kmp_sch_static_chunked
386345153Sdim    if (schedtype == kmp_sch_static) {
387345153Sdim      cur_chunk = trip_count / nth + ((trip_count % nth) ? 1 : 0);
388345153Sdim    }
389345153Sdim    // 0 - "static" schedule
390345153Sdim    __kmp_itt_metadata_loop(loc, 0, trip_count, cur_chunk);
391345153Sdim  }
392345153Sdim#endif
393345153Sdim#ifdef KMP_DEBUG
394345153Sdim  {
395345153Sdim    char *buff;
396345153Sdim    // create format specifiers before the debug output
397345153Sdim    buff = __kmp_str_format("__kmpc_for_static_init: liter=%%d lower=%%%s "
398345153Sdim                            "upper=%%%s stride = %%%s signed?<%s>\n",
399345153Sdim                            traits_t<T>::spec, traits_t<T>::spec,
400345153Sdim                            traits_t<ST>::spec, traits_t<T>::spec);
401345153Sdim    KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
402345153Sdim    __kmp_str_free(&buff);
403345153Sdim  }
404345153Sdim#endif
405345153Sdim  KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
406345153Sdim
407345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
408345153Sdim  if (ompt_enabled.ompt_callback_work) {
409345153Sdim    ompt_callbacks.ompt_callback(ompt_callback_work)(
410345153Sdim        ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
411345153Sdim        &(task_info->task_data), trip_count, codeptr);
412345153Sdim  }
413345153Sdim#endif
414345153Sdim
415353358Sdim  KMP_STATS_LOOP_END(OMP_loop_static_iterations);
416345153Sdim  return;
417345153Sdim}
418345153Sdim
419345153Sdimtemplate <typename T>
420345153Sdimstatic void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid,
421345153Sdim                                       kmp_int32 schedule, kmp_int32 *plastiter,
422345153Sdim                                       T *plower, T *pupper, T *pupperDist,
423345153Sdim                                       typename traits_t<T>::signed_t *pstride,
424345153Sdim                                       typename traits_t<T>::signed_t incr,
425345153Sdim                                       typename traits_t<T>::signed_t chunk) {
426345153Sdim  KMP_COUNT_BLOCK(OMP_DISTRIBUTE);
427353358Sdim  KMP_PUSH_PARTITIONED_TIMER(OMP_distribute);
428353358Sdim  KMP_PUSH_PARTITIONED_TIMER(OMP_distribute_scheduling);
429345153Sdim  typedef typename traits_t<T>::unsigned_t UT;
430345153Sdim  typedef typename traits_t<T>::signed_t ST;
431345153Sdim  kmp_uint32 tid;
432345153Sdim  kmp_uint32 nth;
433345153Sdim  kmp_uint32 team_id;
434345153Sdim  kmp_uint32 nteams;
435345153Sdim  UT trip_count;
436345153Sdim  kmp_team_t *team;
437345153Sdim  kmp_info_t *th;
438345153Sdim
439345153Sdim  KMP_DEBUG_ASSERT(plastiter && plower && pupper && pupperDist && pstride);
440345153Sdim  KE_TRACE(10, ("__kmpc_dist_for_static_init called (%d)\n", gtid));
441345153Sdim#ifdef KMP_DEBUG
442345153Sdim  {
443345153Sdim    char *buff;
444345153Sdim    // create format specifiers before the debug output
445345153Sdim    buff = __kmp_str_format(
446345153Sdim        "__kmpc_dist_for_static_init: T#%%d schedLoop=%%d liter=%%d "
447345153Sdim        "iter=(%%%s, %%%s, %%%s) chunk=%%%s signed?<%s>\n",
448345153Sdim        traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
449345153Sdim        traits_t<ST>::spec, traits_t<T>::spec);
450345153Sdim    KD_TRACE(100,
451345153Sdim             (buff, gtid, schedule, *plastiter, *plower, *pupper, incr, chunk));
452345153Sdim    __kmp_str_free(&buff);
453345153Sdim  }
454345153Sdim#endif
455345153Sdim
456345153Sdim  if (__kmp_env_consistency_check) {
457345153Sdim    __kmp_push_workshare(gtid, ct_pdo, loc);
458345153Sdim    if (incr == 0) {
459345153Sdim      __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
460345153Sdim                            loc);
461345153Sdim    }
462345153Sdim    if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
463345153Sdim      // The loop is illegal.
464345153Sdim      // Some zero-trip loops maintained by compiler, e.g.:
465345153Sdim      //   for(i=10;i<0;++i) // lower >= upper - run-time check
466345153Sdim      //   for(i=0;i>10;--i) // lower <= upper - run-time check
467345153Sdim      //   for(i=0;i>10;++i) // incr > 0       - compile-time check
468345153Sdim      //   for(i=10;i<0;--i) // incr < 0       - compile-time check
469345153Sdim      // Compiler does not check the following illegal loops:
470345153Sdim      //   for(i=0;i<10;i+=incr) // where incr<0
471345153Sdim      //   for(i=10;i>0;i-=incr) // where incr<0
472345153Sdim      __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc);
473345153Sdim    }
474345153Sdim  }
475345153Sdim  tid = __kmp_tid_from_gtid(gtid);
476345153Sdim  th = __kmp_threads[gtid];
477345153Sdim  nth = th->th.th_team_nproc;
478345153Sdim  team = th->th.th_team;
479345153Sdim  KMP_DEBUG_ASSERT(th->th.th_teams_microtask); // we are in the teams construct
480345153Sdim  nteams = th->th.th_teams_size.nteams;
481345153Sdim  team_id = team->t.t_master_tid;
482345153Sdim  KMP_DEBUG_ASSERT(nteams == (kmp_uint32)team->t.t_parent->t.t_nproc);
483345153Sdim
484345153Sdim  // compute global trip count
485345153Sdim  if (incr == 1) {
486345153Sdim    trip_count = *pupper - *plower + 1;
487345153Sdim  } else if (incr == -1) {
488345153Sdim    trip_count = *plower - *pupper + 1;
489345153Sdim  } else if (incr > 0) {
490345153Sdim    // upper-lower can exceed the limit of signed type
491345153Sdim    trip_count = (UT)(*pupper - *plower) / incr + 1;
492345153Sdim  } else {
493345153Sdim    trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
494345153Sdim  }
495345153Sdim
496345153Sdim  *pstride = *pupper - *plower; // just in case (can be unused)
497345153Sdim  if (trip_count <= nteams) {
498345153Sdim    KMP_DEBUG_ASSERT(
499345153Sdim        __kmp_static == kmp_sch_static_greedy ||
500345153Sdim        __kmp_static ==
501345153Sdim            kmp_sch_static_balanced); // Unknown static scheduling type.
502345153Sdim    // only masters of some teams get single iteration, other threads get
503345153Sdim    // nothing
504345153Sdim    if (team_id < trip_count && tid == 0) {
505345153Sdim      *pupper = *pupperDist = *plower = *plower + team_id * incr;
506345153Sdim    } else {
507345153Sdim      *pupperDist = *pupper;
508345153Sdim      *plower = *pupper + incr; // compiler should skip loop body
509345153Sdim    }
510345153Sdim    if (plastiter != NULL)
511345153Sdim      *plastiter = (tid == 0 && team_id == trip_count - 1);
512345153Sdim  } else {
513345153Sdim    // Get the team's chunk first (each team gets at most one chunk)
514345153Sdim    if (__kmp_static == kmp_sch_static_balanced) {
515345153Sdim      UT chunkD = trip_count / nteams;
516345153Sdim      UT extras = trip_count % nteams;
517345153Sdim      *plower +=
518345153Sdim          incr * (team_id * chunkD + (team_id < extras ? team_id : extras));
519345153Sdim      *pupperDist = *plower + chunkD * incr - (team_id < extras ? 0 : incr);
520345153Sdim      if (plastiter != NULL)
521345153Sdim        *plastiter = (team_id == nteams - 1);
522345153Sdim    } else {
523345153Sdim      T chunk_inc_count =
524345153Sdim          (trip_count / nteams + ((trip_count % nteams) ? 1 : 0)) * incr;
525345153Sdim      T upper = *pupper;
526345153Sdim      KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
527345153Sdim      // Unknown static scheduling type.
528345153Sdim      *plower += team_id * chunk_inc_count;
529345153Sdim      *pupperDist = *plower + chunk_inc_count - incr;
530345153Sdim      // Check/correct bounds if needed
531345153Sdim      if (incr > 0) {
532345153Sdim        if (*pupperDist < *plower)
533345153Sdim          *pupperDist = traits_t<T>::max_value;
534345153Sdim        if (plastiter != NULL)
535345153Sdim          *plastiter = *plower <= upper && *pupperDist > upper - incr;
536345153Sdim        if (*pupperDist > upper)
537345153Sdim          *pupperDist = upper; // tracker C73258
538345153Sdim        if (*plower > *pupperDist) {
539345153Sdim          *pupper = *pupperDist; // no iterations available for the team
540345153Sdim          goto end;
541345153Sdim        }
542345153Sdim      } else {
543345153Sdim        if (*pupperDist > *plower)
544345153Sdim          *pupperDist = traits_t<T>::min_value;
545345153Sdim        if (plastiter != NULL)
546345153Sdim          *plastiter = *plower >= upper && *pupperDist < upper - incr;
547345153Sdim        if (*pupperDist < upper)
548345153Sdim          *pupperDist = upper; // tracker C73258
549345153Sdim        if (*plower < *pupperDist) {
550345153Sdim          *pupper = *pupperDist; // no iterations available for the team
551345153Sdim          goto end;
552345153Sdim        }
553345153Sdim      }
554345153Sdim    }
555345153Sdim    // Get the parallel loop chunk now (for thread)
556345153Sdim    // compute trip count for team's chunk
557345153Sdim    if (incr == 1) {
558345153Sdim      trip_count = *pupperDist - *plower + 1;
559345153Sdim    } else if (incr == -1) {
560345153Sdim      trip_count = *plower - *pupperDist + 1;
561345153Sdim    } else if (incr > 1) {
562345153Sdim      // upper-lower can exceed the limit of signed type
563345153Sdim      trip_count = (UT)(*pupperDist - *plower) / incr + 1;
564345153Sdim    } else {
565345153Sdim      trip_count = (UT)(*plower - *pupperDist) / (-incr) + 1;
566345153Sdim    }
567345153Sdim    KMP_DEBUG_ASSERT(trip_count);
568345153Sdim    switch (schedule) {
569345153Sdim    case kmp_sch_static: {
570345153Sdim      if (trip_count <= nth) {
571345153Sdim        KMP_DEBUG_ASSERT(
572345153Sdim            __kmp_static == kmp_sch_static_greedy ||
573345153Sdim            __kmp_static ==
574345153Sdim                kmp_sch_static_balanced); // Unknown static scheduling type.
575345153Sdim        if (tid < trip_count)
576345153Sdim          *pupper = *plower = *plower + tid * incr;
577345153Sdim        else
578345153Sdim          *plower = *pupper + incr; // no iterations available
579345153Sdim        if (plastiter != NULL)
580345153Sdim          if (*plastiter != 0 && !(tid == trip_count - 1))
581345153Sdim            *plastiter = 0;
582345153Sdim      } else {
583345153Sdim        if (__kmp_static == kmp_sch_static_balanced) {
584345153Sdim          UT chunkL = trip_count / nth;
585345153Sdim          UT extras = trip_count % nth;
586345153Sdim          *plower += incr * (tid * chunkL + (tid < extras ? tid : extras));
587345153Sdim          *pupper = *plower + chunkL * incr - (tid < extras ? 0 : incr);
588345153Sdim          if (plastiter != NULL)
589345153Sdim            if (*plastiter != 0 && !(tid == nth - 1))
590345153Sdim              *plastiter = 0;
591345153Sdim        } else {
592345153Sdim          T chunk_inc_count =
593345153Sdim              (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
594345153Sdim          T upper = *pupperDist;
595345153Sdim          KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
596345153Sdim          // Unknown static scheduling type.
597345153Sdim          *plower += tid * chunk_inc_count;
598345153Sdim          *pupper = *plower + chunk_inc_count - incr;
599345153Sdim          if (incr > 0) {
600345153Sdim            if (*pupper < *plower)
601345153Sdim              *pupper = traits_t<T>::max_value;
602345153Sdim            if (plastiter != NULL)
603345153Sdim              if (*plastiter != 0 &&
604345153Sdim                  !(*plower <= upper && *pupper > upper - incr))
605345153Sdim                *plastiter = 0;
606345153Sdim            if (*pupper > upper)
607345153Sdim              *pupper = upper; // tracker C73258
608345153Sdim          } else {
609345153Sdim            if (*pupper > *plower)
610345153Sdim              *pupper = traits_t<T>::min_value;
611345153Sdim            if (plastiter != NULL)
612345153Sdim              if (*plastiter != 0 &&
613345153Sdim                  !(*plower >= upper && *pupper < upper - incr))
614345153Sdim                *plastiter = 0;
615345153Sdim            if (*pupper < upper)
616345153Sdim              *pupper = upper; // tracker C73258
617345153Sdim          }
618345153Sdim        }
619345153Sdim      }
620345153Sdim      break;
621345153Sdim    }
622345153Sdim    case kmp_sch_static_chunked: {
623345153Sdim      ST span;
624345153Sdim      if (chunk < 1)
625345153Sdim        chunk = 1;
626345153Sdim      span = chunk * incr;
627345153Sdim      *pstride = span * nth;
628345153Sdim      *plower = *plower + (span * tid);
629345153Sdim      *pupper = *plower + span - incr;
630345153Sdim      if (plastiter != NULL)
631345153Sdim        if (*plastiter != 0 && !(tid == ((trip_count - 1) / (UT)chunk) % nth))
632345153Sdim          *plastiter = 0;
633345153Sdim      break;
634345153Sdim    }
635345153Sdim    default:
636345153Sdim      KMP_ASSERT2(0,
637345153Sdim                  "__kmpc_dist_for_static_init: unknown loop scheduling type");
638345153Sdim      break;
639345153Sdim    }
640345153Sdim  }
641345153Sdimend:;
642345153Sdim#ifdef KMP_DEBUG
643345153Sdim  {
644345153Sdim    char *buff;
645345153Sdim    // create format specifiers before the debug output
646345153Sdim    buff = __kmp_str_format(
647345153Sdim        "__kmpc_dist_for_static_init: last=%%d lo=%%%s up=%%%s upDist=%%%s "
648345153Sdim        "stride=%%%s signed?<%s>\n",
649345153Sdim        traits_t<T>::spec, traits_t<T>::spec, traits_t<T>::spec,
650345153Sdim        traits_t<ST>::spec, traits_t<T>::spec);
651345153Sdim    KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pupperDist, *pstride));
652345153Sdim    __kmp_str_free(&buff);
653345153Sdim  }
654345153Sdim#endif
655345153Sdim  KE_TRACE(10, ("__kmpc_dist_for_static_init: T#%d return\n", gtid));
656353358Sdim  KMP_STATS_LOOP_END(OMP_distribute_iterations);
657345153Sdim  return;
658345153Sdim}
659345153Sdim
660345153Sdimtemplate <typename T>
661345153Sdimstatic void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid,
662345153Sdim                                   kmp_int32 *p_last, T *p_lb, T *p_ub,
663345153Sdim                                   typename traits_t<T>::signed_t *p_st,
664345153Sdim                                   typename traits_t<T>::signed_t incr,
665345153Sdim                                   typename traits_t<T>::signed_t chunk) {
666345153Sdim  // The routine returns the first chunk distributed to the team and
667345153Sdim  // stride for next chunks calculation.
668345153Sdim  // Last iteration flag set for the team that will execute
669345153Sdim  // the last iteration of the loop.
670345153Sdim  // The routine is called for dist_schedue(static,chunk) only.
671345153Sdim  typedef typename traits_t<T>::unsigned_t UT;
672345153Sdim  typedef typename traits_t<T>::signed_t ST;
673345153Sdim  kmp_uint32 team_id;
674345153Sdim  kmp_uint32 nteams;
675345153Sdim  UT trip_count;
676345153Sdim  T lower;
677345153Sdim  T upper;
678345153Sdim  ST span;
679345153Sdim  kmp_team_t *team;
680345153Sdim  kmp_info_t *th;
681345153Sdim
682345153Sdim  KMP_DEBUG_ASSERT(p_last && p_lb && p_ub && p_st);
683345153Sdim  KE_TRACE(10, ("__kmp_team_static_init called (%d)\n", gtid));
684345153Sdim#ifdef KMP_DEBUG
685345153Sdim  {
686345153Sdim    char *buff;
687345153Sdim    // create format specifiers before the debug output
688345153Sdim    buff = __kmp_str_format("__kmp_team_static_init enter: T#%%d liter=%%d "
689345153Sdim                            "iter=(%%%s, %%%s, %%%s) chunk %%%s; signed?<%s>\n",
690345153Sdim                            traits_t<T>::spec, traits_t<T>::spec,
691345153Sdim                            traits_t<ST>::spec, traits_t<ST>::spec,
692345153Sdim                            traits_t<T>::spec);
693345153Sdim    KD_TRACE(100, (buff, gtid, *p_last, *p_lb, *p_ub, *p_st, chunk));
694345153Sdim    __kmp_str_free(&buff);
695345153Sdim  }
696345153Sdim#endif
697345153Sdim
698345153Sdim  lower = *p_lb;
699345153Sdim  upper = *p_ub;
700345153Sdim  if (__kmp_env_consistency_check) {
701345153Sdim    if (incr == 0) {
702345153Sdim      __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
703345153Sdim                            loc);
704345153Sdim    }
705345153Sdim    if (incr > 0 ? (upper < lower) : (lower < upper)) {
706345153Sdim      // The loop is illegal.
707345153Sdim      // Some zero-trip loops maintained by compiler, e.g.:
708345153Sdim      //   for(i=10;i<0;++i) // lower >= upper - run-time check
709345153Sdim      //   for(i=0;i>10;--i) // lower <= upper - run-time check
710345153Sdim      //   for(i=0;i>10;++i) // incr > 0       - compile-time check
711345153Sdim      //   for(i=10;i<0;--i) // incr < 0       - compile-time check
712345153Sdim      // Compiler does not check the following illegal loops:
713345153Sdim      //   for(i=0;i<10;i+=incr) // where incr<0
714345153Sdim      //   for(i=10;i>0;i-=incr) // where incr<0
715345153Sdim      __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc);
716345153Sdim    }
717345153Sdim  }
718345153Sdim  th = __kmp_threads[gtid];
719345153Sdim  team = th->th.th_team;
720345153Sdim  KMP_DEBUG_ASSERT(th->th.th_teams_microtask); // we are in the teams construct
721345153Sdim  nteams = th->th.th_teams_size.nteams;
722345153Sdim  team_id = team->t.t_master_tid;
723345153Sdim  KMP_DEBUG_ASSERT(nteams == (kmp_uint32)team->t.t_parent->t.t_nproc);
724345153Sdim
725345153Sdim  // compute trip count
726345153Sdim  if (incr == 1) {
727345153Sdim    trip_count = upper - lower + 1;
728345153Sdim  } else if (incr == -1) {
729345153Sdim    trip_count = lower - upper + 1;
730345153Sdim  } else if (incr > 0) {
731345153Sdim    // upper-lower can exceed the limit of signed type
732345153Sdim    trip_count = (UT)(upper - lower) / incr + 1;
733345153Sdim  } else {
734345153Sdim    trip_count = (UT)(lower - upper) / (-incr) + 1;
735345153Sdim  }
736345153Sdim  if (chunk < 1)
737345153Sdim    chunk = 1;
738345153Sdim  span = chunk * incr;
739345153Sdim  *p_st = span * nteams;
740345153Sdim  *p_lb = lower + (span * team_id);
741345153Sdim  *p_ub = *p_lb + span - incr;
742345153Sdim  if (p_last != NULL)
743345153Sdim    *p_last = (team_id == ((trip_count - 1) / (UT)chunk) % nteams);
744345153Sdim  // Correct upper bound if needed
745345153Sdim  if (incr > 0) {
746345153Sdim    if (*p_ub < *p_lb) // overflow?
747345153Sdim      *p_ub = traits_t<T>::max_value;
748345153Sdim    if (*p_ub > upper)
749345153Sdim      *p_ub = upper; // tracker C73258
750345153Sdim  } else { // incr < 0
751345153Sdim    if (*p_ub > *p_lb)
752345153Sdim      *p_ub = traits_t<T>::min_value;
753345153Sdim    if (*p_ub < upper)
754345153Sdim      *p_ub = upper; // tracker C73258
755345153Sdim  }
756345153Sdim#ifdef KMP_DEBUG
757345153Sdim  {
758345153Sdim    char *buff;
759345153Sdim    // create format specifiers before the debug output
760345153Sdim    buff =
761345153Sdim        __kmp_str_format("__kmp_team_static_init exit: T#%%d team%%u liter=%%d "
762345153Sdim                         "iter=(%%%s, %%%s, %%%s) chunk %%%s\n",
763345153Sdim                         traits_t<T>::spec, traits_t<T>::spec,
764345153Sdim                         traits_t<ST>::spec, traits_t<ST>::spec);
765345153Sdim    KD_TRACE(100, (buff, gtid, team_id, *p_last, *p_lb, *p_ub, *p_st, chunk));
766345153Sdim    __kmp_str_free(&buff);
767345153Sdim  }
768345153Sdim#endif
769345153Sdim}
770345153Sdim
771345153Sdim//------------------------------------------------------------------------------
772345153Sdimextern "C" {
773345153Sdim/*!
774345153Sdim@ingroup WORK_SHARING
775345153Sdim@param    loc       Source code location
776345153Sdim@param    gtid      Global thread id of this thread
777345153Sdim@param    schedtype  Scheduling type
778345153Sdim@param    plastiter Pointer to the "last iteration" flag
779345153Sdim@param    plower    Pointer to the lower bound
780345153Sdim@param    pupper    Pointer to the upper bound
781345153Sdim@param    pstride   Pointer to the stride
782345153Sdim@param    incr      Loop increment
783345153Sdim@param    chunk     The chunk size
784345153Sdim
785345153SdimEach of the four functions here are identical apart from the argument types.
786345153Sdim
787345153SdimThe functions compute the upper and lower bounds and stride to be used for the
788345153Sdimset of iterations to be executed by the current thread from the statically
789345153Sdimscheduled loop that is described by the initial values of the bounds, stride,
790345153Sdimincrement and chunk size.
791345153Sdim
792345153Sdim@{
793345153Sdim*/
794345153Sdimvoid __kmpc_for_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype,
795345153Sdim                              kmp_int32 *plastiter, kmp_int32 *plower,
796345153Sdim                              kmp_int32 *pupper, kmp_int32 *pstride,
797345153Sdim                              kmp_int32 incr, kmp_int32 chunk) {
798345153Sdim  __kmp_for_static_init<kmp_int32>(loc, gtid, schedtype, plastiter, plower,
799345153Sdim                                   pupper, pstride, incr, chunk
800345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
801345153Sdim                                   ,
802345153Sdim                                   OMPT_GET_RETURN_ADDRESS(0)
803345153Sdim#endif
804345153Sdim                                       );
805345153Sdim}
806345153Sdim
807345153Sdim/*!
808345153Sdim See @ref __kmpc_for_static_init_4
809345153Sdim */
810345153Sdimvoid __kmpc_for_static_init_4u(ident_t *loc, kmp_int32 gtid,
811345153Sdim                               kmp_int32 schedtype, kmp_int32 *plastiter,
812345153Sdim                               kmp_uint32 *plower, kmp_uint32 *pupper,
813345153Sdim                               kmp_int32 *pstride, kmp_int32 incr,
814345153Sdim                               kmp_int32 chunk) {
815345153Sdim  __kmp_for_static_init<kmp_uint32>(loc, gtid, schedtype, plastiter, plower,
816345153Sdim                                    pupper, pstride, incr, chunk
817345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
818345153Sdim                                    ,
819345153Sdim                                    OMPT_GET_RETURN_ADDRESS(0)
820345153Sdim#endif
821345153Sdim                                        );
822345153Sdim}
823345153Sdim
824345153Sdim/*!
825345153Sdim See @ref __kmpc_for_static_init_4
826345153Sdim */
827345153Sdimvoid __kmpc_for_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype,
828345153Sdim                              kmp_int32 *plastiter, kmp_int64 *plower,
829345153Sdim                              kmp_int64 *pupper, kmp_int64 *pstride,
830345153Sdim                              kmp_int64 incr, kmp_int64 chunk) {
831345153Sdim  __kmp_for_static_init<kmp_int64>(loc, gtid, schedtype, plastiter, plower,
832345153Sdim                                   pupper, pstride, incr, chunk
833345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
834345153Sdim                                   ,
835345153Sdim                                   OMPT_GET_RETURN_ADDRESS(0)
836345153Sdim#endif
837345153Sdim                                       );
838345153Sdim}
839345153Sdim
840345153Sdim/*!
841345153Sdim See @ref __kmpc_for_static_init_4
842345153Sdim */
843345153Sdimvoid __kmpc_for_static_init_8u(ident_t *loc, kmp_int32 gtid,
844345153Sdim                               kmp_int32 schedtype, kmp_int32 *plastiter,
845345153Sdim                               kmp_uint64 *plower, kmp_uint64 *pupper,
846345153Sdim                               kmp_int64 *pstride, kmp_int64 incr,
847345153Sdim                               kmp_int64 chunk) {
848345153Sdim  __kmp_for_static_init<kmp_uint64>(loc, gtid, schedtype, plastiter, plower,
849345153Sdim                                    pupper, pstride, incr, chunk
850345153Sdim#if OMPT_SUPPORT && OMPT_OPTIONAL
851345153Sdim                                    ,
852345153Sdim                                    OMPT_GET_RETURN_ADDRESS(0)
853345153Sdim#endif
854345153Sdim                                        );
855345153Sdim}
856345153Sdim/*!
857345153Sdim@}
858345153Sdim*/
859345153Sdim
860345153Sdim/*!
861345153Sdim@ingroup WORK_SHARING
862345153Sdim@param    loc       Source code location
863345153Sdim@param    gtid      Global thread id of this thread
864345153Sdim@param    schedule  Scheduling type for the parallel loop
865345153Sdim@param    plastiter Pointer to the "last iteration" flag
866345153Sdim@param    plower    Pointer to the lower bound
867345153Sdim@param    pupper    Pointer to the upper bound of loop chunk
868345153Sdim@param    pupperD   Pointer to the upper bound of dist_chunk
869345153Sdim@param    pstride   Pointer to the stride for parallel loop
870345153Sdim@param    incr      Loop increment
871345153Sdim@param    chunk     The chunk size for the parallel loop
872345153Sdim
873345153SdimEach of the four functions here are identical apart from the argument types.
874345153Sdim
875345153SdimThe functions compute the upper and lower bounds and strides to be used for the
876345153Sdimset of iterations to be executed by the current thread from the statically
877345153Sdimscheduled loop that is described by the initial values of the bounds, strides,
878345153Sdimincrement and chunks for parallel loop and distribute constructs.
879345153Sdim
880345153Sdim@{
881345153Sdim*/
882345153Sdimvoid __kmpc_dist_for_static_init_4(ident_t *loc, kmp_int32 gtid,
883345153Sdim                                   kmp_int32 schedule, kmp_int32 *plastiter,
884345153Sdim                                   kmp_int32 *plower, kmp_int32 *pupper,
885345153Sdim                                   kmp_int32 *pupperD, kmp_int32 *pstride,
886345153Sdim                                   kmp_int32 incr, kmp_int32 chunk) {
887345153Sdim  __kmp_dist_for_static_init<kmp_int32>(loc, gtid, schedule, plastiter, plower,
888345153Sdim                                        pupper, pupperD, pstride, incr, chunk);
889345153Sdim}
890345153Sdim
891345153Sdim/*!
892345153Sdim See @ref __kmpc_dist_for_static_init_4
893345153Sdim */
894345153Sdimvoid __kmpc_dist_for_static_init_4u(ident_t *loc, kmp_int32 gtid,
895345153Sdim                                    kmp_int32 schedule, kmp_int32 *plastiter,
896345153Sdim                                    kmp_uint32 *plower, kmp_uint32 *pupper,
897345153Sdim                                    kmp_uint32 *pupperD, kmp_int32 *pstride,
898345153Sdim                                    kmp_int32 incr, kmp_int32 chunk) {
899345153Sdim  __kmp_dist_for_static_init<kmp_uint32>(loc, gtid, schedule, plastiter, plower,
900345153Sdim                                         pupper, pupperD, pstride, incr, chunk);
901345153Sdim}
902345153Sdim
903345153Sdim/*!
904345153Sdim See @ref __kmpc_dist_for_static_init_4
905345153Sdim */
906345153Sdimvoid __kmpc_dist_for_static_init_8(ident_t *loc, kmp_int32 gtid,
907345153Sdim                                   kmp_int32 schedule, kmp_int32 *plastiter,
908345153Sdim                                   kmp_int64 *plower, kmp_int64 *pupper,
909345153Sdim                                   kmp_int64 *pupperD, kmp_int64 *pstride,
910345153Sdim                                   kmp_int64 incr, kmp_int64 chunk) {
911345153Sdim  __kmp_dist_for_static_init<kmp_int64>(loc, gtid, schedule, plastiter, plower,
912345153Sdim                                        pupper, pupperD, pstride, incr, chunk);
913345153Sdim}
914345153Sdim
915345153Sdim/*!
916345153Sdim See @ref __kmpc_dist_for_static_init_4
917345153Sdim */
918345153Sdimvoid __kmpc_dist_for_static_init_8u(ident_t *loc, kmp_int32 gtid,
919345153Sdim                                    kmp_int32 schedule, kmp_int32 *plastiter,
920345153Sdim                                    kmp_uint64 *plower, kmp_uint64 *pupper,
921345153Sdim                                    kmp_uint64 *pupperD, kmp_int64 *pstride,
922345153Sdim                                    kmp_int64 incr, kmp_int64 chunk) {
923345153Sdim  __kmp_dist_for_static_init<kmp_uint64>(loc, gtid, schedule, plastiter, plower,
924345153Sdim                                         pupper, pupperD, pstride, incr, chunk);
925345153Sdim}
926345153Sdim/*!
927345153Sdim@}
928345153Sdim*/
929345153Sdim
930345153Sdim//------------------------------------------------------------------------------
931345153Sdim// Auxiliary routines for Distribute Parallel Loop construct implementation
932345153Sdim//    Transfer call to template< type T >
933345153Sdim//    __kmp_team_static_init( ident_t *loc, int gtid,
934345153Sdim//        int *p_last, T *lb, T *ub, ST *st, ST incr, ST chunk )
935345153Sdim
936345153Sdim/*!
937345153Sdim@ingroup WORK_SHARING
938345153Sdim@{
939345153Sdim@param loc Source location
940345153Sdim@param gtid Global thread id
941345153Sdim@param p_last pointer to last iteration flag
942345153Sdim@param p_lb  pointer to Lower bound
943345153Sdim@param p_ub  pointer to Upper bound
944345153Sdim@param p_st  Step (or increment if you prefer)
945345153Sdim@param incr  Loop increment
946345153Sdim@param chunk The chunk size to block with
947345153Sdim
948345153SdimThe functions compute the upper and lower bounds and stride to be used for the
949345153Sdimset of iterations to be executed by the current team from the statically
950345153Sdimscheduled loop that is described by the initial values of the bounds, stride,
951345153Sdimincrement and chunk for the distribute construct as part of composite distribute
952345153Sdimparallel loop construct. These functions are all identical apart from the types
953345153Sdimof the arguments.
954345153Sdim*/
955345153Sdim
956345153Sdimvoid __kmpc_team_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
957345153Sdim                               kmp_int32 *p_lb, kmp_int32 *p_ub,
958345153Sdim                               kmp_int32 *p_st, kmp_int32 incr,
959345153Sdim                               kmp_int32 chunk) {
960345153Sdim  KMP_DEBUG_ASSERT(__kmp_init_serial);
961345153Sdim  __kmp_team_static_init<kmp_int32>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
962345153Sdim                                    chunk);
963345153Sdim}
964345153Sdim
965345153Sdim/*!
966345153Sdim See @ref __kmpc_team_static_init_4
967345153Sdim */
968345153Sdimvoid __kmpc_team_static_init_4u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
969345153Sdim                                kmp_uint32 *p_lb, kmp_uint32 *p_ub,
970345153Sdim                                kmp_int32 *p_st, kmp_int32 incr,
971345153Sdim                                kmp_int32 chunk) {
972345153Sdim  KMP_DEBUG_ASSERT(__kmp_init_serial);
973345153Sdim  __kmp_team_static_init<kmp_uint32>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
974345153Sdim                                     chunk);
975345153Sdim}
976345153Sdim
977345153Sdim/*!
978345153Sdim See @ref __kmpc_team_static_init_4
979345153Sdim */
980345153Sdimvoid __kmpc_team_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
981345153Sdim                               kmp_int64 *p_lb, kmp_int64 *p_ub,
982345153Sdim                               kmp_int64 *p_st, kmp_int64 incr,
983345153Sdim                               kmp_int64 chunk) {
984345153Sdim  KMP_DEBUG_ASSERT(__kmp_init_serial);
985345153Sdim  __kmp_team_static_init<kmp_int64>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
986345153Sdim                                    chunk);
987345153Sdim}
988345153Sdim
989345153Sdim/*!
990345153Sdim See @ref __kmpc_team_static_init_4
991345153Sdim */
992345153Sdimvoid __kmpc_team_static_init_8u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
993345153Sdim                                kmp_uint64 *p_lb, kmp_uint64 *p_ub,
994345153Sdim                                kmp_int64 *p_st, kmp_int64 incr,
995345153Sdim                                kmp_int64 chunk) {
996345153Sdim  KMP_DEBUG_ASSERT(__kmp_init_serial);
997345153Sdim  __kmp_team_static_init<kmp_uint64>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
998345153Sdim                                     chunk);
999345153Sdim}
1000345153Sdim/*!
1001345153Sdim@}
1002345153Sdim*/
1003345153Sdim
1004345153Sdim} // extern "C"
1005