1 /*
2  * kmp_sched.cpp -- static scheduling -- iteration initialization
3  */
4 
5 //===----------------------------------------------------------------------===//
6 //
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10 //
11 //===----------------------------------------------------------------------===//
12 
13 /* Static scheduling initialization.
14 
15   NOTE: team->t.t_nproc is a constant inside of any dispatch loop, however
16         it may change values between parallel regions.  __kmp_max_nth
17         is the largest value __kmp_nth may take, 1 is the smallest. */
18 
19 #include "kmp.h"
20 #include "kmp_error.h"
21 #include "kmp_i18n.h"
22 #include "kmp_itt.h"
23 #include "kmp_stats.h"
24 #include "kmp_str.h"
25 
26 #if OMPT_SUPPORT
27 #include "ompt-specific.h"
28 #endif
29 
30 #ifdef KMP_DEBUG
31 //-------------------------------------------------------------------------
32 // template for debug prints specification ( d, u, lld, llu )
33 char const *traits_t<int>::spec = "d";
34 char const *traits_t<unsigned int>::spec = "u";
35 char const *traits_t<long long>::spec = "lld";
36 char const *traits_t<unsigned long long>::spec = "llu";
37 char const *traits_t<long>::spec = "ld";
38 //-------------------------------------------------------------------------
39 #endif
40 
41 #if KMP_STATS_ENABLED
42 #define KMP_STATS_LOOP_END(stat)                                               \
43   {                                                                            \
44     kmp_int64 t;                                                               \
45     kmp_int64 u = (kmp_int64)(*pupper);                                        \
46     kmp_int64 l = (kmp_int64)(*plower);                                        \
47     kmp_int64 i = (kmp_int64)incr;                                             \
48     if (i == 1) {                                                              \
49       t = u - l + 1;                                                           \
50     } else if (i == -1) {                                                      \
51       t = l - u + 1;                                                           \
52     } else if (i > 0) {                                                        \
53       t = (u - l) / i + 1;                                                     \
54     } else {                                                                   \
55       t = (l - u) / (-i) + 1;                                                  \
56     }                                                                          \
57     KMP_COUNT_VALUE(stat, t);                                                  \
58     KMP_POP_PARTITIONED_TIMER();                                               \
59   }
60 #else
61 #define KMP_STATS_LOOP_END(stat) /* Nothing */
62 #endif
63 
64 template <typename T>
65 static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid,
66                                   kmp_int32 schedtype, kmp_int32 *plastiter,
67                                   T *plower, T *pupper,
68                                   typename traits_t<T>::signed_t *pstride,
69                                   typename traits_t<T>::signed_t incr,
70                                   typename traits_t<T>::signed_t chunk
71 #if OMPT_SUPPORT && OMPT_OPTIONAL
72                                   ,
73                                   void *codeptr
74 #endif
75                                   ) {
76   KMP_COUNT_BLOCK(OMP_LOOP_STATIC);
77   KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static);
78   KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static_scheduling);
79 
80   typedef typename traits_t<T>::unsigned_t UT;
81   typedef typename traits_t<T>::signed_t ST;
82   /*  this all has to be changed back to TID and such.. */
83   kmp_int32 gtid = global_tid;
84   kmp_uint32 tid;
85   kmp_uint32 nth;
86   UT trip_count;
87   kmp_team_t *team;
88   kmp_info_t *th = __kmp_threads[gtid];
89 
90 #if OMPT_SUPPORT && OMPT_OPTIONAL
91   ompt_team_info_t *team_info = NULL;
92   ompt_task_info_t *task_info = NULL;
93   ompt_work_t ompt_work_type = ompt_work_loop;
94 
95   static kmp_int8 warn = 0;
96 
97   if (ompt_enabled.ompt_callback_work) {
98     // Only fully initialize variables needed by OMPT if OMPT is enabled.
99     team_info = __ompt_get_teaminfo(0, NULL);
100     task_info = __ompt_get_task_info_object(0);
101     // Determine workshare type
102     if (loc != NULL) {
103       if ((loc->flags & KMP_IDENT_WORK_LOOP) != 0) {
104         ompt_work_type = ompt_work_loop;
105       } else if ((loc->flags & KMP_IDENT_WORK_SECTIONS) != 0) {
106         ompt_work_type = ompt_work_sections;
107       } else if ((loc->flags & KMP_IDENT_WORK_DISTRIBUTE) != 0) {
108         ompt_work_type = ompt_work_distribute;
109       } else {
110         kmp_int8 bool_res =
111             KMP_COMPARE_AND_STORE_ACQ8(&warn, (kmp_int8)0, (kmp_int8)1);
112         if (bool_res)
113           KMP_WARNING(OmptOutdatedWorkshare);
114       }
115       KMP_DEBUG_ASSERT(ompt_work_type);
116     }
117   }
118 #endif
119 
120   KMP_DEBUG_ASSERT(plastiter && plower && pupper && pstride);
121   KE_TRACE(10, ("__kmpc_for_static_init called (%d)\n", global_tid));
122 #ifdef KMP_DEBUG
123   {
124     char *buff;
125     // create format specifiers before the debug output
126     buff = __kmp_str_format(
127         "__kmpc_for_static_init: T#%%d sched=%%d liter=%%d iter=(%%%s,"
128         " %%%s, %%%s) incr=%%%s chunk=%%%s signed?<%s>\n",
129         traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
130         traits_t<ST>::spec, traits_t<ST>::spec, traits_t<T>::spec);
131     KD_TRACE(100, (buff, global_tid, schedtype, *plastiter, *plower, *pupper,
132                    *pstride, incr, chunk));
133     __kmp_str_free(&buff);
134   }
135 #endif
136 
137   if (__kmp_env_consistency_check) {
138     __kmp_push_workshare(global_tid, ct_pdo, loc);
139     if (incr == 0) {
140       __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
141                             loc);
142     }
143   }
144   /* special handling for zero-trip loops */
145   if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
146     if (plastiter != NULL)
147       *plastiter = FALSE;
148     /* leave pupper and plower set to entire iteration space */
149     *pstride = incr; /* value should never be used */
150 // *plower = *pupper - incr;
151 // let compiler bypass the illegal loop (like for(i=1;i<10;i--))
152 // THE LINE COMMENTED ABOVE CAUSED shape2F/h_tests_1.f TO HAVE A FAILURE
153 // ON A ZERO-TRIP LOOP (lower=1, upper=0,stride=1) - JPH June 23, 2009.
154 #ifdef KMP_DEBUG
155     {
156       char *buff;
157       // create format specifiers before the debug output
158       buff = __kmp_str_format("__kmpc_for_static_init:(ZERO TRIP) liter=%%d "
159                               "lower=%%%s upper=%%%s stride = %%%s "
160                               "signed?<%s>, loc = %%s\n",
161                               traits_t<T>::spec, traits_t<T>::spec,
162                               traits_t<ST>::spec, traits_t<T>::spec);
163       KD_TRACE(100,
164                (buff, *plastiter, *plower, *pupper, *pstride, loc->psource));
165       __kmp_str_free(&buff);
166     }
167 #endif
168     KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
169 
170 #if OMPT_SUPPORT && OMPT_OPTIONAL
171     if (ompt_enabled.ompt_callback_work) {
172       ompt_callbacks.ompt_callback(ompt_callback_work)(
173           ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
174           &(task_info->task_data), 0, codeptr);
175     }
176 #endif
177     KMP_STATS_LOOP_END(OMP_loop_static_iterations);
178     return;
179   }
180 
181   // Although there are schedule enumerations above kmp_ord_upper which are not
182   // schedules for "distribute", the only ones which are useful are dynamic, so
183   // cannot be seen here, since this codepath is only executed for static
184   // schedules.
185   if (schedtype > kmp_ord_upper) {
186     // we are in DISTRIBUTE construct
187     schedtype += kmp_sch_static -
188                  kmp_distribute_static; // AC: convert to usual schedule type
189     tid = th->th.th_team->t.t_master_tid;
190     team = th->th.th_team->t.t_parent;
191   } else {
192     tid = __kmp_tid_from_gtid(global_tid);
193     team = th->th.th_team;
194   }
195 
196   /* determine if "for" loop is an active worksharing construct */
197   if (team->t.t_serialized) {
198     /* serialized parallel, each thread executes whole iteration space */
199     if (plastiter != NULL)
200       *plastiter = TRUE;
201     /* leave pupper and plower set to entire iteration space */
202     *pstride =
203         (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
204 
205 #ifdef KMP_DEBUG
206     {
207       char *buff;
208       // create format specifiers before the debug output
209       buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
210                               "lower=%%%s upper=%%%s stride = %%%s\n",
211                               traits_t<T>::spec, traits_t<T>::spec,
212                               traits_t<ST>::spec);
213       KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
214       __kmp_str_free(&buff);
215     }
216 #endif
217     KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
218 
219 #if OMPT_SUPPORT && OMPT_OPTIONAL
220     if (ompt_enabled.ompt_callback_work) {
221       ompt_callbacks.ompt_callback(ompt_callback_work)(
222           ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
223           &(task_info->task_data), *pstride, codeptr);
224     }
225 #endif
226     KMP_STATS_LOOP_END(OMP_loop_static_iterations);
227     return;
228   }
229   nth = team->t.t_nproc;
230   if (nth == 1) {
231     if (plastiter != NULL)
232       *plastiter = TRUE;
233     *pstride =
234         (incr > 0) ? (*pupper - *plower + 1) : (-(*plower - *pupper + 1));
235 #ifdef KMP_DEBUG
236     {
237       char *buff;
238       // create format specifiers before the debug output
239       buff = __kmp_str_format("__kmpc_for_static_init: (serial) liter=%%d "
240                               "lower=%%%s upper=%%%s stride = %%%s\n",
241                               traits_t<T>::spec, traits_t<T>::spec,
242                               traits_t<ST>::spec);
243       KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
244       __kmp_str_free(&buff);
245     }
246 #endif
247     KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
248 
249 #if OMPT_SUPPORT && OMPT_OPTIONAL
250     if (ompt_enabled.ompt_callback_work) {
251       ompt_callbacks.ompt_callback(ompt_callback_work)(
252           ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
253           &(task_info->task_data), *pstride, codeptr);
254     }
255 #endif
256     KMP_STATS_LOOP_END(OMP_loop_static_iterations);
257     return;
258   }
259 
260   /* compute trip count */
261   if (incr == 1) {
262     trip_count = *pupper - *plower + 1;
263   } else if (incr == -1) {
264     trip_count = *plower - *pupper + 1;
265   } else if (incr > 0) {
266     // upper-lower can exceed the limit of signed type
267     trip_count = (UT)(*pupper - *plower) / incr + 1;
268   } else {
269     trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
270   }
271 
272 #if KMP_STATS_ENABLED
273   if (KMP_MASTER_GTID(gtid)) {
274     KMP_COUNT_VALUE(OMP_loop_static_total_iterations, trip_count);
275   }
276 #endif
277 
278   if (__kmp_env_consistency_check) {
279     /* tripcount overflow? */
280     if (trip_count == 0 && *pupper != *plower) {
281       __kmp_error_construct(kmp_i18n_msg_CnsIterationRangeTooLarge, ct_pdo,
282                             loc);
283     }
284   }
285 
286   /* compute remaining parameters */
287   switch (schedtype) {
288   case kmp_sch_static: {
289     if (trip_count < nth) {
290       KMP_DEBUG_ASSERT(
291           __kmp_static == kmp_sch_static_greedy ||
292           __kmp_static ==
293               kmp_sch_static_balanced); // Unknown static scheduling type.
294       if (tid < trip_count) {
295         *pupper = *plower = *plower + tid * incr;
296       } else {
297         *plower = *pupper + incr;
298       }
299       if (plastiter != NULL)
300         *plastiter = (tid == trip_count - 1);
301     } else {
302       if (__kmp_static == kmp_sch_static_balanced) {
303         UT small_chunk = trip_count / nth;
304         UT extras = trip_count % nth;
305         *plower += incr * (tid * small_chunk + (tid < extras ? tid : extras));
306         *pupper = *plower + small_chunk * incr - (tid < extras ? 0 : incr);
307         if (plastiter != NULL)
308           *plastiter = (tid == nth - 1);
309       } else {
310         T big_chunk_inc_count =
311             (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
312         T old_upper = *pupper;
313 
314         KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
315         // Unknown static scheduling type.
316 
317         *plower += tid * big_chunk_inc_count;
318         *pupper = *plower + big_chunk_inc_count - incr;
319         if (incr > 0) {
320           if (*pupper < *plower)
321             *pupper = traits_t<T>::max_value;
322           if (plastiter != NULL)
323             *plastiter = *plower <= old_upper && *pupper > old_upper - incr;
324           if (*pupper > old_upper)
325             *pupper = old_upper; // tracker C73258
326         } else {
327           if (*pupper > *plower)
328             *pupper = traits_t<T>::min_value;
329           if (plastiter != NULL)
330             *plastiter = *plower >= old_upper && *pupper < old_upper - incr;
331           if (*pupper < old_upper)
332             *pupper = old_upper; // tracker C73258
333         }
334       }
335     }
336     *pstride = trip_count;
337     break;
338   }
339   case kmp_sch_static_chunked: {
340     ST span;
341     if (chunk < 1) {
342       chunk = 1;
343     }
344     span = chunk * incr;
345     *pstride = span * nth;
346     *plower = *plower + (span * tid);
347     *pupper = *plower + span - incr;
348     if (plastiter != NULL)
349       *plastiter = (tid == ((trip_count - 1) / (UT)chunk) % nth);
350     break;
351   }
352   case kmp_sch_static_balanced_chunked: {
353     T old_upper = *pupper;
354     // round up to make sure the chunk is enough to cover all iterations
355     UT span = (trip_count + nth - 1) / nth;
356 
357     // perform chunk adjustment
358     chunk = (span + chunk - 1) & ~(chunk - 1);
359 
360     span = chunk * incr;
361     *plower = *plower + (span * tid);
362     *pupper = *plower + span - incr;
363     if (incr > 0) {
364       if (*pupper > old_upper)
365         *pupper = old_upper;
366     } else if (*pupper < old_upper)
367       *pupper = old_upper;
368 
369     if (plastiter != NULL)
370       *plastiter = (tid == ((trip_count - 1) / (UT)chunk));
371     break;
372   }
373   default:
374     KMP_ASSERT2(0, "__kmpc_for_static_init: unknown scheduling type");
375     break;
376   }
377 
378 #if USE_ITT_BUILD
379   // Report loop metadata
380   if (KMP_MASTER_TID(tid) && __itt_metadata_add_ptr &&
381       __kmp_forkjoin_frames_mode == 3 && th->th.th_teams_microtask == NULL &&
382       team->t.t_active_level == 1) {
383     kmp_uint64 cur_chunk = chunk;
384     // Calculate chunk in case it was not specified; it is specified for
385     // kmp_sch_static_chunked
386     if (schedtype == kmp_sch_static) {
387       cur_chunk = trip_count / nth + ((trip_count % nth) ? 1 : 0);
388     }
389     // 0 - "static" schedule
390     __kmp_itt_metadata_loop(loc, 0, trip_count, cur_chunk);
391   }
392 #endif
393 #ifdef KMP_DEBUG
394   {
395     char *buff;
396     // create format specifiers before the debug output
397     buff = __kmp_str_format("__kmpc_for_static_init: liter=%%d lower=%%%s "
398                             "upper=%%%s stride = %%%s signed?<%s>\n",
399                             traits_t<T>::spec, traits_t<T>::spec,
400                             traits_t<ST>::spec, traits_t<T>::spec);
401     KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pstride));
402     __kmp_str_free(&buff);
403   }
404 #endif
405   KE_TRACE(10, ("__kmpc_for_static_init: T#%d return\n", global_tid));
406 
407 #if OMPT_SUPPORT && OMPT_OPTIONAL
408   if (ompt_enabled.ompt_callback_work) {
409     ompt_callbacks.ompt_callback(ompt_callback_work)(
410         ompt_work_type, ompt_scope_begin, &(team_info->parallel_data),
411         &(task_info->task_data), trip_count, codeptr);
412   }
413 #endif
414 
415   KMP_STATS_LOOP_END(OMP_loop_static_iterations);
416   return;
417 }
418 
419 template <typename T>
420 static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid,
421                                        kmp_int32 schedule, kmp_int32 *plastiter,
422                                        T *plower, T *pupper, T *pupperDist,
423                                        typename traits_t<T>::signed_t *pstride,
424                                        typename traits_t<T>::signed_t incr,
425                                        typename traits_t<T>::signed_t chunk) {
426   KMP_COUNT_BLOCK(OMP_DISTRIBUTE);
427   KMP_PUSH_PARTITIONED_TIMER(OMP_distribute);
428   KMP_PUSH_PARTITIONED_TIMER(OMP_distribute_scheduling);
429   typedef typename traits_t<T>::unsigned_t UT;
430   typedef typename traits_t<T>::signed_t ST;
431   kmp_uint32 tid;
432   kmp_uint32 nth;
433   kmp_uint32 team_id;
434   kmp_uint32 nteams;
435   UT trip_count;
436   kmp_team_t *team;
437   kmp_info_t *th;
438 
439   KMP_DEBUG_ASSERT(plastiter && plower && pupper && pupperDist && pstride);
440   KE_TRACE(10, ("__kmpc_dist_for_static_init called (%d)\n", gtid));
441 #ifdef KMP_DEBUG
442   {
443     char *buff;
444     // create format specifiers before the debug output
445     buff = __kmp_str_format(
446         "__kmpc_dist_for_static_init: T#%%d schedLoop=%%d liter=%%d "
447         "iter=(%%%s, %%%s, %%%s) chunk=%%%s signed?<%s>\n",
448         traits_t<T>::spec, traits_t<T>::spec, traits_t<ST>::spec,
449         traits_t<ST>::spec, traits_t<T>::spec);
450     KD_TRACE(100,
451              (buff, gtid, schedule, *plastiter, *plower, *pupper, incr, chunk));
452     __kmp_str_free(&buff);
453   }
454 #endif
455 
456   if (__kmp_env_consistency_check) {
457     __kmp_push_workshare(gtid, ct_pdo, loc);
458     if (incr == 0) {
459       __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
460                             loc);
461     }
462     if (incr > 0 ? (*pupper < *plower) : (*plower < *pupper)) {
463       // The loop is illegal.
464       // Some zero-trip loops maintained by compiler, e.g.:
465       //   for(i=10;i<0;++i) // lower >= upper - run-time check
466       //   for(i=0;i>10;--i) // lower <= upper - run-time check
467       //   for(i=0;i>10;++i) // incr > 0       - compile-time check
468       //   for(i=10;i<0;--i) // incr < 0       - compile-time check
469       // Compiler does not check the following illegal loops:
470       //   for(i=0;i<10;i+=incr) // where incr<0
471       //   for(i=10;i>0;i-=incr) // where incr<0
472       __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc);
473     }
474   }
475   tid = __kmp_tid_from_gtid(gtid);
476   th = __kmp_threads[gtid];
477   nth = th->th.th_team_nproc;
478   team = th->th.th_team;
479   KMP_DEBUG_ASSERT(th->th.th_teams_microtask); // we are in the teams construct
480   nteams = th->th.th_teams_size.nteams;
481   team_id = team->t.t_master_tid;
482   KMP_DEBUG_ASSERT(nteams == (kmp_uint32)team->t.t_parent->t.t_nproc);
483 
484   // compute global trip count
485   if (incr == 1) {
486     trip_count = *pupper - *plower + 1;
487   } else if (incr == -1) {
488     trip_count = *plower - *pupper + 1;
489   } else if (incr > 0) {
490     // upper-lower can exceed the limit of signed type
491     trip_count = (UT)(*pupper - *plower) / incr + 1;
492   } else {
493     trip_count = (UT)(*plower - *pupper) / (-incr) + 1;
494   }
495 
496   *pstride = *pupper - *plower; // just in case (can be unused)
497   if (trip_count <= nteams) {
498     KMP_DEBUG_ASSERT(
499         __kmp_static == kmp_sch_static_greedy ||
500         __kmp_static ==
501             kmp_sch_static_balanced); // Unknown static scheduling type.
502     // only masters of some teams get single iteration, other threads get
503     // nothing
504     if (team_id < trip_count && tid == 0) {
505       *pupper = *pupperDist = *plower = *plower + team_id * incr;
506     } else {
507       *pupperDist = *pupper;
508       *plower = *pupper + incr; // compiler should skip loop body
509     }
510     if (plastiter != NULL)
511       *plastiter = (tid == 0 && team_id == trip_count - 1);
512   } else {
513     // Get the team's chunk first (each team gets at most one chunk)
514     if (__kmp_static == kmp_sch_static_balanced) {
515       UT chunkD = trip_count / nteams;
516       UT extras = trip_count % nteams;
517       *plower +=
518           incr * (team_id * chunkD + (team_id < extras ? team_id : extras));
519       *pupperDist = *plower + chunkD * incr - (team_id < extras ? 0 : incr);
520       if (plastiter != NULL)
521         *plastiter = (team_id == nteams - 1);
522     } else {
523       T chunk_inc_count =
524           (trip_count / nteams + ((trip_count % nteams) ? 1 : 0)) * incr;
525       T upper = *pupper;
526       KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
527       // Unknown static scheduling type.
528       *plower += team_id * chunk_inc_count;
529       *pupperDist = *plower + chunk_inc_count - incr;
530       // Check/correct bounds if needed
531       if (incr > 0) {
532         if (*pupperDist < *plower)
533           *pupperDist = traits_t<T>::max_value;
534         if (plastiter != NULL)
535           *plastiter = *plower <= upper && *pupperDist > upper - incr;
536         if (*pupperDist > upper)
537           *pupperDist = upper; // tracker C73258
538         if (*plower > *pupperDist) {
539           *pupper = *pupperDist; // no iterations available for the team
540           goto end;
541         }
542       } else {
543         if (*pupperDist > *plower)
544           *pupperDist = traits_t<T>::min_value;
545         if (plastiter != NULL)
546           *plastiter = *plower >= upper && *pupperDist < upper - incr;
547         if (*pupperDist < upper)
548           *pupperDist = upper; // tracker C73258
549         if (*plower < *pupperDist) {
550           *pupper = *pupperDist; // no iterations available for the team
551           goto end;
552         }
553       }
554     }
555     // Get the parallel loop chunk now (for thread)
556     // compute trip count for team's chunk
557     if (incr == 1) {
558       trip_count = *pupperDist - *plower + 1;
559     } else if (incr == -1) {
560       trip_count = *plower - *pupperDist + 1;
561     } else if (incr > 1) {
562       // upper-lower can exceed the limit of signed type
563       trip_count = (UT)(*pupperDist - *plower) / incr + 1;
564     } else {
565       trip_count = (UT)(*plower - *pupperDist) / (-incr) + 1;
566     }
567     KMP_DEBUG_ASSERT(trip_count);
568     switch (schedule) {
569     case kmp_sch_static: {
570       if (trip_count <= nth) {
571         KMP_DEBUG_ASSERT(
572             __kmp_static == kmp_sch_static_greedy ||
573             __kmp_static ==
574                 kmp_sch_static_balanced); // Unknown static scheduling type.
575         if (tid < trip_count)
576           *pupper = *plower = *plower + tid * incr;
577         else
578           *plower = *pupper + incr; // no iterations available
579         if (plastiter != NULL)
580           if (*plastiter != 0 && !(tid == trip_count - 1))
581             *plastiter = 0;
582       } else {
583         if (__kmp_static == kmp_sch_static_balanced) {
584           UT chunkL = trip_count / nth;
585           UT extras = trip_count % nth;
586           *plower += incr * (tid * chunkL + (tid < extras ? tid : extras));
587           *pupper = *plower + chunkL * incr - (tid < extras ? 0 : incr);
588           if (plastiter != NULL)
589             if (*plastiter != 0 && !(tid == nth - 1))
590               *plastiter = 0;
591         } else {
592           T chunk_inc_count =
593               (trip_count / nth + ((trip_count % nth) ? 1 : 0)) * incr;
594           T upper = *pupperDist;
595           KMP_DEBUG_ASSERT(__kmp_static == kmp_sch_static_greedy);
596           // Unknown static scheduling type.
597           *plower += tid * chunk_inc_count;
598           *pupper = *plower + chunk_inc_count - incr;
599           if (incr > 0) {
600             if (*pupper < *plower)
601               *pupper = traits_t<T>::max_value;
602             if (plastiter != NULL)
603               if (*plastiter != 0 &&
604                   !(*plower <= upper && *pupper > upper - incr))
605                 *plastiter = 0;
606             if (*pupper > upper)
607               *pupper = upper; // tracker C73258
608           } else {
609             if (*pupper > *plower)
610               *pupper = traits_t<T>::min_value;
611             if (plastiter != NULL)
612               if (*plastiter != 0 &&
613                   !(*plower >= upper && *pupper < upper - incr))
614                 *plastiter = 0;
615             if (*pupper < upper)
616               *pupper = upper; // tracker C73258
617           }
618         }
619       }
620       break;
621     }
622     case kmp_sch_static_chunked: {
623       ST span;
624       if (chunk < 1)
625         chunk = 1;
626       span = chunk * incr;
627       *pstride = span * nth;
628       *plower = *plower + (span * tid);
629       *pupper = *plower + span - incr;
630       if (plastiter != NULL)
631         if (*plastiter != 0 && !(tid == ((trip_count - 1) / (UT)chunk) % nth))
632           *plastiter = 0;
633       break;
634     }
635     default:
636       KMP_ASSERT2(0,
637                   "__kmpc_dist_for_static_init: unknown loop scheduling type");
638       break;
639     }
640   }
641 end:;
642 #ifdef KMP_DEBUG
643   {
644     char *buff;
645     // create format specifiers before the debug output
646     buff = __kmp_str_format(
647         "__kmpc_dist_for_static_init: last=%%d lo=%%%s up=%%%s upDist=%%%s "
648         "stride=%%%s signed?<%s>\n",
649         traits_t<T>::spec, traits_t<T>::spec, traits_t<T>::spec,
650         traits_t<ST>::spec, traits_t<T>::spec);
651     KD_TRACE(100, (buff, *plastiter, *plower, *pupper, *pupperDist, *pstride));
652     __kmp_str_free(&buff);
653   }
654 #endif
655   KE_TRACE(10, ("__kmpc_dist_for_static_init: T#%d return\n", gtid));
656   KMP_STATS_LOOP_END(OMP_distribute_iterations);
657   return;
658 }
659 
660 template <typename T>
661 static void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid,
662                                    kmp_int32 *p_last, T *p_lb, T *p_ub,
663                                    typename traits_t<T>::signed_t *p_st,
664                                    typename traits_t<T>::signed_t incr,
665                                    typename traits_t<T>::signed_t chunk) {
666   // The routine returns the first chunk distributed to the team and
667   // stride for next chunks calculation.
668   // Last iteration flag set for the team that will execute
669   // the last iteration of the loop.
670   // The routine is called for dist_schedue(static,chunk) only.
671   typedef typename traits_t<T>::unsigned_t UT;
672   typedef typename traits_t<T>::signed_t ST;
673   kmp_uint32 team_id;
674   kmp_uint32 nteams;
675   UT trip_count;
676   T lower;
677   T upper;
678   ST span;
679   kmp_team_t *team;
680   kmp_info_t *th;
681 
682   KMP_DEBUG_ASSERT(p_last && p_lb && p_ub && p_st);
683   KE_TRACE(10, ("__kmp_team_static_init called (%d)\n", gtid));
684 #ifdef KMP_DEBUG
685   {
686     char *buff;
687     // create format specifiers before the debug output
688     buff = __kmp_str_format("__kmp_team_static_init enter: T#%%d liter=%%d "
689                             "iter=(%%%s, %%%s, %%%s) chunk %%%s; signed?<%s>\n",
690                             traits_t<T>::spec, traits_t<T>::spec,
691                             traits_t<ST>::spec, traits_t<ST>::spec,
692                             traits_t<T>::spec);
693     KD_TRACE(100, (buff, gtid, *p_last, *p_lb, *p_ub, *p_st, chunk));
694     __kmp_str_free(&buff);
695   }
696 #endif
697 
698   lower = *p_lb;
699   upper = *p_ub;
700   if (__kmp_env_consistency_check) {
701     if (incr == 0) {
702       __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrZeroProhibited, ct_pdo,
703                             loc);
704     }
705     if (incr > 0 ? (upper < lower) : (lower < upper)) {
706       // The loop is illegal.
707       // Some zero-trip loops maintained by compiler, e.g.:
708       //   for(i=10;i<0;++i) // lower >= upper - run-time check
709       //   for(i=0;i>10;--i) // lower <= upper - run-time check
710       //   for(i=0;i>10;++i) // incr > 0       - compile-time check
711       //   for(i=10;i<0;--i) // incr < 0       - compile-time check
712       // Compiler does not check the following illegal loops:
713       //   for(i=0;i<10;i+=incr) // where incr<0
714       //   for(i=10;i>0;i-=incr) // where incr<0
715       __kmp_error_construct(kmp_i18n_msg_CnsLoopIncrIllegal, ct_pdo, loc);
716     }
717   }
718   th = __kmp_threads[gtid];
719   team = th->th.th_team;
720   KMP_DEBUG_ASSERT(th->th.th_teams_microtask); // we are in the teams construct
721   nteams = th->th.th_teams_size.nteams;
722   team_id = team->t.t_master_tid;
723   KMP_DEBUG_ASSERT(nteams == (kmp_uint32)team->t.t_parent->t.t_nproc);
724 
725   // compute trip count
726   if (incr == 1) {
727     trip_count = upper - lower + 1;
728   } else if (incr == -1) {
729     trip_count = lower - upper + 1;
730   } else if (incr > 0) {
731     // upper-lower can exceed the limit of signed type
732     trip_count = (UT)(upper - lower) / incr + 1;
733   } else {
734     trip_count = (UT)(lower - upper) / (-incr) + 1;
735   }
736   if (chunk < 1)
737     chunk = 1;
738   span = chunk * incr;
739   *p_st = span * nteams;
740   *p_lb = lower + (span * team_id);
741   *p_ub = *p_lb + span - incr;
742   if (p_last != NULL)
743     *p_last = (team_id == ((trip_count - 1) / (UT)chunk) % nteams);
744   // Correct upper bound if needed
745   if (incr > 0) {
746     if (*p_ub < *p_lb) // overflow?
747       *p_ub = traits_t<T>::max_value;
748     if (*p_ub > upper)
749       *p_ub = upper; // tracker C73258
750   } else { // incr < 0
751     if (*p_ub > *p_lb)
752       *p_ub = traits_t<T>::min_value;
753     if (*p_ub < upper)
754       *p_ub = upper; // tracker C73258
755   }
756 #ifdef KMP_DEBUG
757   {
758     char *buff;
759     // create format specifiers before the debug output
760     buff =
761         __kmp_str_format("__kmp_team_static_init exit: T#%%d team%%u liter=%%d "
762                          "iter=(%%%s, %%%s, %%%s) chunk %%%s\n",
763                          traits_t<T>::spec, traits_t<T>::spec,
764                          traits_t<ST>::spec, traits_t<ST>::spec);
765     KD_TRACE(100, (buff, gtid, team_id, *p_last, *p_lb, *p_ub, *p_st, chunk));
766     __kmp_str_free(&buff);
767   }
768 #endif
769 }
770 
771 //------------------------------------------------------------------------------
772 extern "C" {
773 /*!
774 @ingroup WORK_SHARING
775 @param    loc       Source code location
776 @param    gtid      Global thread id of this thread
777 @param    schedtype  Scheduling type
778 @param    plastiter Pointer to the "last iteration" flag
779 @param    plower    Pointer to the lower bound
780 @param    pupper    Pointer to the upper bound
781 @param    pstride   Pointer to the stride
782 @param    incr      Loop increment
783 @param    chunk     The chunk size
784 
785 Each of the four functions here are identical apart from the argument types.
786 
787 The functions compute the upper and lower bounds and stride to be used for the
788 set of iterations to be executed by the current thread from the statically
789 scheduled loop that is described by the initial values of the bounds, stride,
790 increment and chunk size.
791 
792 @{
793 */
794 void __kmpc_for_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype,
795                               kmp_int32 *plastiter, kmp_int32 *plower,
796                               kmp_int32 *pupper, kmp_int32 *pstride,
797                               kmp_int32 incr, kmp_int32 chunk) {
798   __kmp_for_static_init<kmp_int32>(loc, gtid, schedtype, plastiter, plower,
799                                    pupper, pstride, incr, chunk
800 #if OMPT_SUPPORT && OMPT_OPTIONAL
801                                    ,
802                                    OMPT_GET_RETURN_ADDRESS(0)
803 #endif
804                                        );
805 }
806 
807 /*!
808  See @ref __kmpc_for_static_init_4
809  */
810 void __kmpc_for_static_init_4u(ident_t *loc, kmp_int32 gtid,
811                                kmp_int32 schedtype, kmp_int32 *plastiter,
812                                kmp_uint32 *plower, kmp_uint32 *pupper,
813                                kmp_int32 *pstride, kmp_int32 incr,
814                                kmp_int32 chunk) {
815   __kmp_for_static_init<kmp_uint32>(loc, gtid, schedtype, plastiter, plower,
816                                     pupper, pstride, incr, chunk
817 #if OMPT_SUPPORT && OMPT_OPTIONAL
818                                     ,
819                                     OMPT_GET_RETURN_ADDRESS(0)
820 #endif
821                                         );
822 }
823 
824 /*!
825  See @ref __kmpc_for_static_init_4
826  */
827 void __kmpc_for_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 schedtype,
828                               kmp_int32 *plastiter, kmp_int64 *plower,
829                               kmp_int64 *pupper, kmp_int64 *pstride,
830                               kmp_int64 incr, kmp_int64 chunk) {
831   __kmp_for_static_init<kmp_int64>(loc, gtid, schedtype, plastiter, plower,
832                                    pupper, pstride, incr, chunk
833 #if OMPT_SUPPORT && OMPT_OPTIONAL
834                                    ,
835                                    OMPT_GET_RETURN_ADDRESS(0)
836 #endif
837                                        );
838 }
839 
840 /*!
841  See @ref __kmpc_for_static_init_4
842  */
843 void __kmpc_for_static_init_8u(ident_t *loc, kmp_int32 gtid,
844                                kmp_int32 schedtype, kmp_int32 *plastiter,
845                                kmp_uint64 *plower, kmp_uint64 *pupper,
846                                kmp_int64 *pstride, kmp_int64 incr,
847                                kmp_int64 chunk) {
848   __kmp_for_static_init<kmp_uint64>(loc, gtid, schedtype, plastiter, plower,
849                                     pupper, pstride, incr, chunk
850 #if OMPT_SUPPORT && OMPT_OPTIONAL
851                                     ,
852                                     OMPT_GET_RETURN_ADDRESS(0)
853 #endif
854                                         );
855 }
856 /*!
857 @}
858 */
859 
860 /*!
861 @ingroup WORK_SHARING
862 @param    loc       Source code location
863 @param    gtid      Global thread id of this thread
864 @param    schedule  Scheduling type for the parallel loop
865 @param    plastiter Pointer to the "last iteration" flag
866 @param    plower    Pointer to the lower bound
867 @param    pupper    Pointer to the upper bound of loop chunk
868 @param    pupperD   Pointer to the upper bound of dist_chunk
869 @param    pstride   Pointer to the stride for parallel loop
870 @param    incr      Loop increment
871 @param    chunk     The chunk size for the parallel loop
872 
873 Each of the four functions here are identical apart from the argument types.
874 
875 The functions compute the upper and lower bounds and strides to be used for the
876 set of iterations to be executed by the current thread from the statically
877 scheduled loop that is described by the initial values of the bounds, strides,
878 increment and chunks for parallel loop and distribute constructs.
879 
880 @{
881 */
882 void __kmpc_dist_for_static_init_4(ident_t *loc, kmp_int32 gtid,
883                                    kmp_int32 schedule, kmp_int32 *plastiter,
884                                    kmp_int32 *plower, kmp_int32 *pupper,
885                                    kmp_int32 *pupperD, kmp_int32 *pstride,
886                                    kmp_int32 incr, kmp_int32 chunk) {
887   __kmp_dist_for_static_init<kmp_int32>(loc, gtid, schedule, plastiter, plower,
888                                         pupper, pupperD, pstride, incr, chunk);
889 }
890 
891 /*!
892  See @ref __kmpc_dist_for_static_init_4
893  */
894 void __kmpc_dist_for_static_init_4u(ident_t *loc, kmp_int32 gtid,
895                                     kmp_int32 schedule, kmp_int32 *plastiter,
896                                     kmp_uint32 *plower, kmp_uint32 *pupper,
897                                     kmp_uint32 *pupperD, kmp_int32 *pstride,
898                                     kmp_int32 incr, kmp_int32 chunk) {
899   __kmp_dist_for_static_init<kmp_uint32>(loc, gtid, schedule, plastiter, plower,
900                                          pupper, pupperD, pstride, incr, chunk);
901 }
902 
903 /*!
904  See @ref __kmpc_dist_for_static_init_4
905  */
906 void __kmpc_dist_for_static_init_8(ident_t *loc, kmp_int32 gtid,
907                                    kmp_int32 schedule, kmp_int32 *plastiter,
908                                    kmp_int64 *plower, kmp_int64 *pupper,
909                                    kmp_int64 *pupperD, kmp_int64 *pstride,
910                                    kmp_int64 incr, kmp_int64 chunk) {
911   __kmp_dist_for_static_init<kmp_int64>(loc, gtid, schedule, plastiter, plower,
912                                         pupper, pupperD, pstride, incr, chunk);
913 }
914 
915 /*!
916  See @ref __kmpc_dist_for_static_init_4
917  */
918 void __kmpc_dist_for_static_init_8u(ident_t *loc, kmp_int32 gtid,
919                                     kmp_int32 schedule, kmp_int32 *plastiter,
920                                     kmp_uint64 *plower, kmp_uint64 *pupper,
921                                     kmp_uint64 *pupperD, kmp_int64 *pstride,
922                                     kmp_int64 incr, kmp_int64 chunk) {
923   __kmp_dist_for_static_init<kmp_uint64>(loc, gtid, schedule, plastiter, plower,
924                                          pupper, pupperD, pstride, incr, chunk);
925 }
926 /*!
927 @}
928 */
929 
930 //------------------------------------------------------------------------------
931 // Auxiliary routines for Distribute Parallel Loop construct implementation
932 //    Transfer call to template< type T >
933 //    __kmp_team_static_init( ident_t *loc, int gtid,
934 //        int *p_last, T *lb, T *ub, ST *st, ST incr, ST chunk )
935 
936 /*!
937 @ingroup WORK_SHARING
938 @{
939 @param loc Source location
940 @param gtid Global thread id
941 @param p_last pointer to last iteration flag
942 @param p_lb  pointer to Lower bound
943 @param p_ub  pointer to Upper bound
944 @param p_st  Step (or increment if you prefer)
945 @param incr  Loop increment
946 @param chunk The chunk size to block with
947 
948 The functions compute the upper and lower bounds and stride to be used for the
949 set of iterations to be executed by the current team from the statically
950 scheduled loop that is described by the initial values of the bounds, stride,
951 increment and chunk for the distribute construct as part of composite distribute
952 parallel loop construct. These functions are all identical apart from the types
953 of the arguments.
954 */
955 
956 void __kmpc_team_static_init_4(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
957                                kmp_int32 *p_lb, kmp_int32 *p_ub,
958                                kmp_int32 *p_st, kmp_int32 incr,
959                                kmp_int32 chunk) {
960   KMP_DEBUG_ASSERT(__kmp_init_serial);
961   __kmp_team_static_init<kmp_int32>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
962                                     chunk);
963 }
964 
965 /*!
966  See @ref __kmpc_team_static_init_4
967  */
968 void __kmpc_team_static_init_4u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
969                                 kmp_uint32 *p_lb, kmp_uint32 *p_ub,
970                                 kmp_int32 *p_st, kmp_int32 incr,
971                                 kmp_int32 chunk) {
972   KMP_DEBUG_ASSERT(__kmp_init_serial);
973   __kmp_team_static_init<kmp_uint32>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
974                                      chunk);
975 }
976 
977 /*!
978  See @ref __kmpc_team_static_init_4
979  */
980 void __kmpc_team_static_init_8(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
981                                kmp_int64 *p_lb, kmp_int64 *p_ub,
982                                kmp_int64 *p_st, kmp_int64 incr,
983                                kmp_int64 chunk) {
984   KMP_DEBUG_ASSERT(__kmp_init_serial);
985   __kmp_team_static_init<kmp_int64>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
986                                     chunk);
987 }
988 
989 /*!
990  See @ref __kmpc_team_static_init_4
991  */
992 void __kmpc_team_static_init_8u(ident_t *loc, kmp_int32 gtid, kmp_int32 *p_last,
993                                 kmp_uint64 *p_lb, kmp_uint64 *p_ub,
994                                 kmp_int64 *p_st, kmp_int64 incr,
995                                 kmp_int64 chunk) {
996   KMP_DEBUG_ASSERT(__kmp_init_serial);
997   __kmp_team_static_init<kmp_uint64>(loc, gtid, p_last, p_lb, p_ub, p_st, incr,
998                                      chunk);
999 }
1000 /*!
1001 @}
1002 */
1003 
1004 } // extern "C"
1005