diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2883,6 +2883,14 @@ bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule, /* Chunked */ Chunk != nullptr) && HasChunkSizeOne && isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()); + bool IsMonotonic = + Ordered || + ((ScheduleKind.Schedule == OMPC_SCHEDULE_static || + ScheduleKind.Schedule == OMPC_SCHEDULE_unknown) && + !(ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || + ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) || + ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic || + ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic; if ((RT.isStaticNonchunked(ScheduleKind.Schedule, /* Chunked */ Chunk != nullptr) || StaticChunkedOne) && @@ -2891,9 +2899,9 @@ getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); emitCommonSimdLoop( *this, S, - [&S](CodeGenFunction &CGF, PrePostActionTy &) { + [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) { if (isOpenMPSimdDirective(S.getDirectiveKind())) { - CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true); + CGF.EmitOMPSimdInit(S, IsMonotonic); } else if (const auto *C = S.getSingleClause()) { if (C->getKind() == OMPC_ORDER_concurrent) CGF.LoopStack.setParallel(/*Enable=*/true); @@ -2950,11 +2958,6 @@ }; OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); } else { - const bool IsMonotonic = - Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static || - ScheduleKind.Schedule == OMPC_SCHEDULE_unknown || - ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic || - ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic; // Emit the outer loop, which requests its work chunk [LB..UB] from // runtime and runs the inner loop to process it. const OMPLoopArguments LoopArguments( diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -13174,7 +13174,9 @@ // OpenMP, 2.7.1, Loop Construct, Restrictions // The nonmonotonic modifier can only be specified with schedule(dynamic) or // schedule(guided). - if ((M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || + // OpenMP 5.0 does not have this restriction. + if (LangOpts.OpenMP < 50 && + (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic || M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) && Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) { Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc, diff --git a/clang/test/OpenMP/for_ast_print.cpp b/clang/test/OpenMP/for_ast_print.cpp --- a/clang/test/OpenMP/for_ast_print.cpp +++ b/clang/test/OpenMP/for_ast_print.cpp @@ -112,6 +112,66 @@ a = 2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; +#pragma omp for schedule(nonmonotonic: dynamic) + // CHECK-NEXT: #pragma omp for schedule(nonmonotonic: dynamic) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(monotonic : dynamic) + // CHECK-NEXT: #pragma omp for schedule(monotonic: dynamic) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(nonmonotonic : guided) + // CHECK-NEXT: #pragma omp for schedule(nonmonotonic: guided) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(monotonic : guided) + // CHECK-NEXT: #pragma omp for schedule(monotonic: guided) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(nonmonotonic : static) + // CHECK-NEXT: #pragma omp for schedule(nonmonotonic: static) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(monotonic :static) + // CHECK-NEXT: #pragma omp for schedule(monotonic: static) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(nonmonotonic : auto) + // CHECK-NEXT: #pragma omp for schedule(nonmonotonic: auto) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(monotonic : auto) + // CHECK-NEXT: #pragma omp for schedule(monotonic: auto) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(nonmonotonic : runtime) + // CHECK-NEXT: #pragma omp for schedule(nonmonotonic: runtime) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; +#pragma omp for schedule(monotonic : runtime) + // CHECK-NEXT: #pragma omp for schedule(monotonic: runtime) + for (int i = 0; i < 2; ++i) + a = 2; +// CHECK-NEXT: for (int i = 0; i < 2; ++i) +// CHECK-NEXT: a = 2; #pragma omp parallel #pragma omp for allocate(argc) private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait for (auto &x : arr) { diff --git a/clang/test/OpenMP/for_schedule_messages.cpp b/clang/test/OpenMP/for_schedule_messages.cpp --- a/clang/test/OpenMP/for_schedule_messages.cpp +++ b/clang/test/OpenMP/for_schedule_messages.cpp @@ -1,6 +1,8 @@ -// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 %s -Wuninitialized -// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized void foo() { } @@ -32,7 +34,7 @@ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; #pragma omp for schedule (monotonic, auto // expected-error {{expected ')'}} expected-warning {{missing ':' after schedule modifier - ignoring}} expected-error {{expected 'simd' in OpenMP clause 'schedule'}} expected-note {{to match this '('}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; - #pragma omp for schedule (nonmonotonic: auto, // expected-error {{expected ')'}} expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} expected-note {{to match this '('}} + #pragma omp for schedule (nonmonotonic: auto, // expected-error {{expected ')'}} omp45-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} expected-note {{to match this '('}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; #pragma omp for schedule (auto, // expected-error {{expected ')'}} expected-note {{to match this '('}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; @@ -61,11 +63,11 @@ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; #pragma omp for schedule (static, N) // expected-error {{argument to 'schedule' clause must be a strictly positive integer value}} for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; - #pragma omp for schedule (nonmonotonic: static) // expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} + #pragma omp for schedule (nonmonotonic: static) // omp45-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; - #pragma omp for schedule (nonmonotonic: auto) // expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} + #pragma omp for schedule (nonmonotonic: auto) // omp45-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; - #pragma omp for schedule (nonmonotonic: runtime) // expected-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} + #pragma omp for schedule (nonmonotonic: runtime) // omp45-error {{'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind}} for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; #pragma omp for schedule (monotonic, nonmonotonic: auto) // expected-error {{modifier 'nonmonotonic' cannot be used along with modifier 'monotonic'}} for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; diff --git a/clang/test/OpenMP/schedule_codegen.cpp b/clang/test/OpenMP/schedule_codegen.cpp --- a/clang/test/OpenMP/schedule_codegen.cpp +++ b/clang/test/OpenMP/schedule_codegen.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} int main() { @@ -134,6 +134,18 @@ // CHECK: !llvm.access.group #pragma omp for simd schedule(nonmonotonic: dynamic) for(int i = 0; i < 10; ++i); +// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32 1073741858, +// CHECK: !llvm.access.group +#pragma omp for simd schedule(nonmonotonic: static) + for(int i = 0; i < 10; ++i); +// CHECK: call void @__kmpc_dispatch_init_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32 1073741862, +// CHECK: !llvm.access.group +#pragma omp for schedule(nonmonotonic: auto) + for(int i = 0; i < 10; ++i); +// CHECK: call void @__kmpc_dispatch_init_4(%struct.ident_t* {{.+}}, i32 %{{.+}}, i32 1073741861, +// CHECK: !llvm.access.group +#pragma omp for simd schedule(nonmonotonic: runtime) + for(int i = 0; i < 10; ++i); // CHECK: @__kmpc_dispatch_init // CHECK-NOT: !llvm.access.group // CHECK: @__kmpc_dispatch_next