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