
Implement the remaining GOMP_* functions to support task reductions in taskgroup, parallel, loop, and taskloop constructs. The unused mem argument to many of the work-sharing constructs has to do with the scan() directive/ inscan() modifier. If mem is set, each function will call KMP_FATAL() and tell the user scan/inscan is unsupported. The GOMP reduction implementation is kept separate from our implementation because of how GOMP presents reduction data and computes the reductions. GOMP expects the privatized copies to be present even after a #pragma omp parallel reduction(task:...) region has ended so the data is stored inside GOMP's uintptr_t* data pseudo-structure. This style is tightly coupled with GCC compiler codegen. There also isn't any init(), combiner(), fini() functions in GOMP's codegen so the two implementations were to disparate to try to wrap GOMP's around our own. Differential Revision: https://reviews.llvm.org/D98806
43 lines
812 B
C
43 lines
812 B
C
// RUN: %libomp-compile-and-run
|
|
|
|
// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
int a = 0, b = 1;
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
#pragma omp parallel
|
|
#pragma omp single
|
|
{
|
|
#pragma omp taskgroup task_reduction(+: a) task_reduction(*: b)
|
|
{
|
|
int i;
|
|
for (i = 1; i <= 5; ++i) {
|
|
#pragma omp task in_reduction(+: a) in_reduction(*: b)
|
|
{
|
|
a += i;
|
|
b *= i;
|
|
#pragma omp task in_reduction(+: a)
|
|
{
|
|
a += i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (a != 30) {
|
|
fprintf(stderr, "error: a != 30. Instead a = %d\n", a);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (b != 120) {
|
|
fprintf(stderr, "error: b != 120. Instead b = %d\n", b);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|