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) &&
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<OMPOrderClause>()) {
if (C->getKind() == OMPC_ORDER_concurrent)
CGF.LoopStack.setParallel(/*Enable=*/true);
};
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(
// 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,
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) {
-// 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() {
}
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];
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];
-// 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() {
// 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