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