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