| // SPMD no-loop distribute: the index is BId * NumThreads + TId, so a NumThreads |
| // larger than the real block size drops iterations. |
| // |
| // The entry is called directly because no C/C++ construct reaches it: clang |
| // emits __kmpc_for_static_init_4, only flang emits this one. |
| // |
| // RUN: %libomptarget-compile-run-and-check-generic |
| // REQUIRES: gpu |
| |
| #include <omp.h> |
| #include <stdio.h> |
| |
| #define N 128 |
| #define NUM_THREADS 256 |
| #define THREAD_LIMIT 32 |
| |
| struct Args { |
| double *Out; |
| }; |
| |
| #pragma omp begin declare target |
| extern void __kmpc_distribute_for_static_loop_4u( |
| void *Loc, void (*Fn)(unsigned, void *), void *Arg, unsigned NumIters, |
| unsigned NumThreads, unsigned BlockChunk, unsigned ThreadChunk, |
| unsigned char OneIterationPerThread); |
| |
| __attribute__((noinline)) static void body(unsigned I, void *A) { |
| ((struct Args *)A)->Out[I] = (double)(I + 1); |
| } |
| #pragma omp end declare target |
| |
| // For the host fallback copy only; the device uses the runtime's definition. |
| #ifndef __AMDGCN__ |
| void __kmpc_distribute_for_static_loop_4u( |
| void *Loc, void (*Fn)(unsigned, void *), void *Arg, unsigned NumIters, |
| unsigned NumThreads, unsigned BlockChunk, unsigned ThreadChunk, |
| unsigned char OneIterationPerThread) { |
| for (unsigned I = 0; I < NumIters; ++I) |
| Fn(I, Arg); |
| } |
| #endif |
| |
| int main(void) { |
| static double Out[N]; |
| for (int I = 0; I < N; ++I) |
| Out[I] = -1.0; |
| |
| // NUM_THREADS deliberately exceeds the block's actual thread count. |
| #pragma omp target teams map(tofrom : Out[0 : N]) num_teams(4) \ |
| thread_limit(THREAD_LIMIT) |
| { |
| #pragma omp parallel |
| { |
| struct Args A; |
| A.Out = Out; |
| __kmpc_distribute_for_static_loop_4u(0, body, &A, N, NUM_THREADS, |
| /*BlockChunk=*/0, |
| /*ThreadChunk=*/0, |
| /*OneIterationPerThread=*/1); |
| } |
| } |
| |
| int Unwritten = 0; |
| for (int I = 0; I < N; ++I) |
| if (Out[I] == -1.0) |
| ++Unwritten; |
| |
| // CHECK: unwritten: 0 |
| printf("unwritten: %d\n", Unwritten); |
| return 0; |
| } |