From: Alexey Bataev Date: Tue, 4 Aug 2015 11:18:19 +0000 (+0000) Subject: [OPENMP 4.1] Support for 'linear' clause in loop directives. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e77f872c9e6df55132bcdde21289fefdb87452e9;p=clang [OPENMP 4.1] Support for 'linear' clause in loop directives. OpenMP 4.1 allows 'linear' clause in loop directives. Patch adds support for it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243969 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index e555833ada..302a30d61a 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -163,6 +163,7 @@ OPENMP_FOR_CLAUSE(collapse) OPENMP_FOR_CLAUSE(schedule) OPENMP_FOR_CLAUSE(ordered) OPENMP_FOR_CLAUSE(nowait) +OPENMP_FOR_CLAUSE(linear) // Clauses allowed for directive 'omp for simd'. OPENMP_FOR_SIMD_CLAUSE(private) @@ -224,6 +225,7 @@ OPENMP_PARALLEL_FOR_CLAUSE(lastprivate) OPENMP_PARALLEL_FOR_CLAUSE(collapse) OPENMP_PARALLEL_FOR_CLAUSE(schedule) OPENMP_PARALLEL_FOR_CLAUSE(ordered) +OPENMP_PARALLEL_FOR_CLAUSE(linear) // Clauses allowed for OpenMP directive 'parallel for simd'. OPENMP_PARALLEL_FOR_SIMD_CLAUSE(if) diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 773cf00f40..ac2440cacd 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -3384,6 +3384,16 @@ StmtResult Sema::ActOnOpenMPForDirective( assert((CurContext->isDependentContext() || B.builtAll()) && "omp for loop exprs were not built"); + if (!CurContext->isDependentContext()) { + // Finalize the clauses that need pre-built expressions for CodeGen. + for (auto C : Clauses) { + if (auto LC = dyn_cast(C)) + if (FinishOpenMPLinearClause(*LC, cast(B.IterationVarRef), + B.NumIterations, *this, CurScope)) + return StmtError(); + } + } + getCurFunction()->setHasBranchProtectedScope(); return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); @@ -3540,6 +3550,16 @@ StmtResult Sema::ActOnOpenMPParallelForDirective( assert((CurContext->isDependentContext() || B.builtAll()) && "omp parallel for loop exprs were not built"); + if (!CurContext->isDependentContext()) { + // Finalize the clauses that need pre-built expressions for CodeGen. + for (auto C : Clauses) { + if (auto LC = dyn_cast(C)) + if (FinishOpenMPLinearClause(*LC, cast(B.IterationVarRef), + B.NumIterations, *this, CurScope)) + return StmtError(); + } + } + getCurFunction()->setHasBranchProtectedScope(); return OMPParallelForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); diff --git a/test/OpenMP/for_ast_print.cpp b/test/OpenMP/for_ast_print.cpp index d87cece176..1af391d2cf 100644 --- a/test/OpenMP/for_ast_print.cpp +++ b/test/OpenMP/for_ast_print.cpp @@ -13,37 +13,37 @@ T tmain(T argc) { T b = argc, c, d, e, f, g; static T a; // CHECK: static T a; -#pragma omp for schedule(dynamic) - // CHECK-NEXT: #pragma omp for schedule(dynamic) +#pragma omp for schedule(dynamic) linear(a) + // CHECK-NEXT: #pragma omp for schedule(dynamic) linear(a) 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 private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait - for (int i = 0; i < 10; ++i) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int i = 0; i < 10; ++i) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) +#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait linear(a : N) + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) nowait - // CHECK-NEXT: for (int i = 0; i < 10; ++i) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int i = 0; i < 10; ++i) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) nowait linear(a: N) + // CHECK-NEXT: for (int i = 0; i < 2; ++i) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int i = 0; i < 2; ++i) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) // CHECK-NEXT: foo(); return T(); } @@ -59,12 +59,12 @@ int main(int argc, char **argv) { // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: a = 2; #pragma omp parallel -#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered nowait +#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered nowait linear(g:-1) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) foo(); // CHECK-NEXT: #pragma omp parallel - // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered nowait + // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered nowait linear(g: -1) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: foo(); diff --git a/test/OpenMP/for_firstprivate_messages.cpp b/test/OpenMP/for_firstprivate_messages.cpp index 2ec81104e7..8caed3b722 100644 --- a/test/OpenMP/for_firstprivate_messages.cpp +++ b/test/OpenMP/for_firstprivate_messages.cpp @@ -114,10 +114,6 @@ int foomain(int argc, char **argv) { #pragma omp for firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp parallel -#pragma omp for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}} - for (int k = 0; k < argc; ++k) - ++k; #pragma omp parallel { int v = 0; diff --git a/test/OpenMP/for_lastprivate_messages.cpp b/test/OpenMP/for_lastprivate_messages.cpp index 2fa14b63bd..63ee82c920 100644 --- a/test/OpenMP/for_lastprivate_messages.cpp +++ b/test/OpenMP/for_lastprivate_messages.cpp @@ -116,10 +116,6 @@ int foomain(int argc, char **argv) { #pragma omp for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp parallel -#pragma omp for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}} - for (int k = 0; k < argc; ++k) - ++k; #pragma omp parallel { int v = 0; diff --git a/test/OpenMP/for_linear_codegen.cpp b/test/OpenMP/for_linear_codegen.cpp new file mode 100644 index 0000000000..0bd573d5dc --- /dev/null +++ b/test/OpenMP/for_linear_codegen.cpp @@ -0,0 +1,263 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s +// expected-no-diagnostics +// REQUIRES: x86-registered-target +#ifndef HEADER +#define HEADER + +template +struct S { + T f; + S(T a) : f(a) {} + S() : f() {} + S &operator=(const S &); + operator T() { return T(); } + ~S() {} +}; + +volatile int g = 1212; +float f; +char cnt; + +// CHECK: [[S_FLOAT_TY:%.+]] = type { float } +// CHECK: [[CAP_MAIN_TY:%.+]] = type { float**, i64* } +// CHECK: [[S_INT_TY:%.+]] = type { i32 } +// CHECK: [[CAP_TMAIN_TY:%.+]] = type { i32**, i32* } +// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8* +// CHECK-DAG: [[F:@.+]] = global float 0.0 +// CHECK-DAG: [[CNT:@.+]] = global i8 0 +template +T tmain() { + S test; + T *pvar = &test.f; + T lvar = T(); +#pragma omp parallel +#pragma omp for linear(pvar, lvar) + for (int i = 0; i < 2; ++i) { + ++pvar, ++lvar; + } + return T(); +} + +int main() { +#ifdef LAMBDA + // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212, + // LAMBDA-LABEL: @main + // LAMBDA: call void [[OUTER_LAMBDA:@.+]]( + [&]() { + // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]]( + // LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}}) +#pragma omp parallel +#pragma omp for linear(g:5) + for (int i = 0; i < 2; ++i) { + // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, + // LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], + // LAMBDA: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}} + // LAMBDA: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]] + // LAMBDA: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) + // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]] + // LAMBDA: [[CNT:%.+]] = load i32, i32* + // LAMBDA: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5 + // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]] + // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]], + // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], 5 + // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** [[G_PRIVATE_ADDR_REF]] + // LAMBDA: call void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]]) + // LAMBDA: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]]) + g += 5; + // LAMBDA: call i32 @__kmpc_cancel_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]]) + [&]() { + // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]]) + // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]], + g = 2; + // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]] + // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]] + // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]] + }(); + } + }(); + return 0; +#elif defined(BLOCKS) + // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212, + // BLOCKS-LABEL: @main + // BLOCKS: call void {{%.+}}(i8 + ^{ + // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8* + // BLOCKS: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}}) +#pragma omp parallel +#pragma omp for linear(g:5) + for (int i = 0; i < 2; ++i) { + // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, + // BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], + // BLOCKS: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}} + // BLOCKS: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]] + // BLOCKS: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) + // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]] + // BLOCKS: [[CNT:%.+]] = load i32, i32* + // BLOCKS: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5 + // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]] + // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]], + // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], 5 + // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]] + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: call void {{%.+}}(i8 + // BLOCKS: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]]) + g += 5; + // BLOCKS: call i32 @__kmpc_cancel_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]]) + g = 1; + ^{ + // BLOCKS: define {{.+}} void {{@.+}}(i8* + g = 2; + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: store i{{[0-9]+}} 2, i{{[0-9]+}}* + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: ret + }(); + } + }(); + return 0; +#else + S test; + float *pvar = &test.f; + long long lvar = 0; +#pragma omp parallel +#pragma omp for linear(pvar, lvar : 3) + for (int i = 0; i < 2; ++i) { + pvar += 3, lvar += 3; + } + return tmain(); +#endif +} + +// CHECK: define i{{[0-9]+}} @main() +// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]], +// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]]) +// CHECK: %{{.+}} = bitcast [[CAP_MAIN_TY]]* +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_MAIN_TY]]*)* [[MAIN_MICROTASK:@.+]] to void +// CHECK: = call {{.+}} [[TMAIN_INT:@.+]]() +// CHECK: call void [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]* +// CHECK: ret + +// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_MAIN_TY]]* %{{.+}}) +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_START:%.+]] = alloca float*, +// CHECK: [[LVAR_START:%.+]] = alloca i64, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_PRIV:%.+]] = alloca float*, +// CHECK: [[LVAR_PRIV:%.+]] = alloca i64, +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]] + +// Check for default initialization. +// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[PVAR_REF:%.+]] = load float**, float*** [[PVAR_PTR_REF]], +// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_REF]], +// CHECK: store float* [[PVAR_VAL]], float** [[PVAR_START]], +// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: [[LVAR_REF:%.+]] = load i64*, i64** [[LVAR_PTR_REF]], +// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_REF]], +// CHECK: store i64 [[LVAR_VAL]], i64* [[LVAR_START]], +// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) +// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3 +// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64 +// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 [[IDX]] +// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3 +// CHECK: [[CONV:%.+]] = sext i32 [[MUL]] to i64 +// CHECK: [[VAL:%.+]] = add nsw i64 [[LVAR_VAL]], [[CONV]] +// CHECK: store i64 [[VAL]], i64* [[LVAR_PRIV]], +// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_PRIV]] +// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 3 +// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_PRIV]], +// CHECK: [[ADD:%.+]] = add nsw i64 [[LVAR_VAL]], 3 +// CHECK: store i64 [[ADD]], i64* [[LVAR_PRIV]], +// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}}) +// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: ret void + +// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]() +// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]], +// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]]) +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_TMAIN_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void +// CHECK: call void [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]* +// CHECK: ret +// +// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_TMAIN_TY]]* %{{.+}}) +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_START:%.+]] = alloca i32*, +// CHECK: [[LVAR_START:%.+]] = alloca i32, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_PRIV:%.+]] = alloca i32*, +// CHECK: [[LVAR_PRIV:%.+]] = alloca i32, +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]] + +// Check for default initialization. +// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[PVAR_REF:%.+]] = load i32**, i32*** [[PVAR_PTR_REF]], +// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_REF]], +// CHECK: store i32* [[PVAR_VAL]], i32** [[PVAR_START]], +// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: [[LVAR_REF:%.+]] = load i32*, i32** [[LVAR_PTR_REF]], +// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_REF]], +// CHECK: store i32 [[LVAR_VAL]], i32* [[LVAR_START]], +// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) +// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1 +// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64 +// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i64 [[IDX]] +// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1 +// CHECK: [[VAL:%.+]] = add nsw i32 [[LVAR_VAL]], [[MUL]] +// CHECK: store i32 [[VAL]], i32* [[LVAR_PRIV]], +// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_PRIV]] +// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i32 1 +// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_PRIV]], +// CHECK: [[ADD:%.+]] = add nsw i32 [[LVAR_VAL]], 1 +// CHECK: store i32 [[ADD]], i32* [[LVAR_PRIV]], +// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}}) +// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: ret void +#endif + diff --git a/test/OpenMP/for_linear_messages.cpp b/test/OpenMP/for_linear_messages.cpp new file mode 100644 index 0000000000..7d8a3330e4 --- /dev/null +++ b/test/OpenMP/for_linear_messages.cpp @@ -0,0 +1,214 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +namespace X { + int x; +}; + +struct B { + static int ib; // expected-note {{'B::ib' declared here}} + static int bfoo() { return 8; } +}; + +int bfoo() { return 4; } + +int z; +const int C1 = 1; +const int C2 = 2; +void test_linear_colons() +{ + int B = 0; + #pragma omp for linear(B:bfoo()) + for (int i = 0; i < 10; ++i) ; + // expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'}} + #pragma omp for linear(B::ib:B:bfoo()) + for (int i = 0; i < 10; ++i) ; + // expected-error@+1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}} + #pragma omp for linear(B:ib) + for (int i = 0; i < 10; ++i) ; + // expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'?}} + #pragma omp for linear(z:B:ib) + for (int i = 0; i < 10; ++i) ; + #pragma omp for linear(B:B::bfoo()) + for (int i = 0; i < 10; ++i) ; + #pragma omp for linear(X::x : ::z) + for (int i = 0; i < 10; ++i) ; + #pragma omp for linear(B,::z, X::x) + for (int i = 0; i < 10; ++i) ; + #pragma omp for linear(::z) + for (int i = 0; i < 10; ++i) ; + // expected-error@+1 {{expected variable name}} + #pragma omp for linear(B::bfoo()) + for (int i = 0; i < 10; ++i) ; + #pragma omp for linear(B::ib,B:C1+C2) + for (int i = 0; i < 10; ++i) ; +} + +template T test_template(T* arr, N num) { + N i; + T sum = (T)0; + T ind2 = - num * L; // expected-note {{'ind2' defined here}} + // expected-error@+1 {{argument of a linear clause should be of integral or pointer type}} +#pragma omp for linear(ind2:L) + for (i = 0; i < num; ++i) { + T cur = arr[(int)ind2]; + ind2 += L; + sum += cur; + } + return T(); +} + +template int test_warn() { + int ind2 = 0; + // expected-warning@+1 {{zero linear step (ind2 should probably be const)}} + #pragma omp for linear(ind2:LEN) + for (int i = 0; i < 100; i++) { + ind2 += LEN; + } + return ind2; +} + +struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; +public: + S2():a(0) { } +}; +const S2 b; // expected-note 2 {{'b' defined here}} +const S2 ba[5]; +class S3 { + int a; +public: + S3():a(0) { } +}; +const S3 ca[5]; +class S4 { + int a; + S4(); +public: + S4(int v):a(v) { } +}; +class S5 { + int a; + S5():a(0) {} +public: + S5(int v):a(v) { } +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +template int foomain(I argc, C **argv) { + I e(4); + I g(5); + int i; + int &j = i; // expected-note {{'j' defined here}} + #pragma omp for linear // expected-error {{expected '(' after 'linear'}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear () // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc : 5) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + // expected-error@+2 {{linear variable with incomplete type 'S1'}} + // expected-error@+1 {{const-qualified variable cannot be linear}} + #pragma omp for linear (a, b:B::ib) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear(e, g) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear(i) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp parallel + { + int v = 0; + int i; + #pragma omp for linear(v:i) + for (int k = 0; k < argc; ++k) { i = k; v += i; } + } + #pragma omp for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type}} + for (int k = 0; k < argc; ++k) ++k; + int v = 0; + #pragma omp for linear(v:j) + for (int k = 0; k < argc; ++k) { ++k; v += j; } + #pragma omp for linear(i) + for (int k = 0; k < argc; ++k) ++k; + return 0; +} + +namespace A { +double x; +#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} +} +namespace C { +using A::x; +} + +int main(int argc, char **argv) { + double darr[100]; + // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}} + test_template<-4>(darr, 4); + // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}} + test_warn<0>(); + + S4 e(4); // expected-note {{'e' defined here}} + S5 g(5); // expected-note {{'g' defined here}} + int i; + int &j = i; // expected-note {{'j' defined here}} + #pragma omp for linear // expected-error {{expected '(' after 'linear'}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear () // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argc) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) ++k; + // expected-error@+2 {{linear variable with incomplete type 'S1'}} + // expected-error@+1 {{const-qualified variable cannot be linear}} + #pragma omp for linear(a, b) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear (argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) ++k; + // expected-error@+2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}} + // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}} + #pragma omp for linear(e, g) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp parallel + { + int i; + #pragma omp for linear(i) + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear(i : 4) + for (int k = 0; k < argc; ++k) { ++k; i += 4; } + } + #pragma omp for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type 'int &'}} + for (int k = 0; k < argc; ++k) ++k; + #pragma omp for linear(i) + for (int k = 0; k < argc; ++k) ++k; + + foomain(argc,argv); + return 0; +} + diff --git a/test/OpenMP/for_loop_messages.cpp b/test/OpenMP/for_loop_messages.cpp index ba27934b11..8dbd9a3bff 100644 --- a/test/OpenMP/for_loop_messages.cpp +++ b/test/OpenMP/for_loop_messages.cpp @@ -289,7 +289,6 @@ int test_iteration_spaces() { c[ii] = a[ii]; #pragma omp parallel -// expected-error@+3 {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}} // expected-note@+2 {{defined as linear}} // expected-error@+2 {{loop iteration variable in the associated loop of 'omp for' directive may not be linear, predetermined as private}} #pragma omp for linear(ii) diff --git a/test/OpenMP/for_misc_messages.c b/test/OpenMP/for_misc_messages.c index f5b8751494..fa42d074b2 100644 --- a/test/OpenMP/for_misc_messages.c +++ b/test/OpenMP/for_misc_messages.c @@ -62,9 +62,8 @@ void test_non_identifiers() { #pragma omp for; for (i = 0; i < 16; ++i) ; +// expected-warning@+2 {{extra tokens at the end of '#pragma omp for' are ignored}} #pragma omp parallel -// expected-error@+2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}} -// expected-warning@+1 {{extra tokens at the end of '#pragma omp for' are ignored}} #pragma omp for linear(x); for (i = 0; i < 16; ++i) ; diff --git a/test/OpenMP/parallel_for_ast_print.cpp b/test/OpenMP/parallel_for_ast_print.cpp index f3025ced3b..7450c7531d 100644 --- a/test/OpenMP/parallel_for_ast_print.cpp +++ b/test/OpenMP/parallel_for_ast_print.cpp @@ -15,35 +15,35 @@ T tmain(T argc) { // CHECK: static T a; static T g; #pragma omp threadprivate(g) -#pragma omp parallel for schedule(dynamic) default(none) copyin(g) - // CHECK: #pragma omp parallel for schedule(dynamic) default(none) copyin(g) +#pragma omp parallel for schedule(dynamic) default(none) copyin(g) linear(a) + // CHECK: #pragma omp parallel for schedule(dynamic) default(none) copyin(g) linear(a) 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 for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) if (argc) num_threads(N) default(shared) shared(e) reduction(+ : h) - for (int i = 0; i < 10; ++i) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int i = 0; i < 10; ++i) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) - for (int j = 0; j < 10; ++j) +#pragma omp parallel for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) if (argc) num_threads(N) default(shared) shared(e) reduction(+ : h) linear(a:N) + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) + for (int j = 0; j < 2; ++j) foo(); - // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) if(argc) num_threads(N) default(shared) shared(e) reduction(+: h) - // CHECK-NEXT: for (int i = 0; i < 10; ++i) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int i = 0; i < 10; ++i) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) - // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) if(argc) num_threads(N) default(shared) shared(e) reduction(+: h) linear(a: N) + // CHECK-NEXT: for (int i = 0; i < 2; ++i) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int i = 0; i < 2; ++i) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) + // CHECK-NEXT: for (int j = 0; j < 2; ++j) // CHECK-NEXT: foo(); return T(); } @@ -54,18 +54,18 @@ int main(int argc, char **argv) { // CHECK: static int a; static float g; #pragma omp threadprivate(g) -#pragma omp parallel for schedule(guided, argc) default(none) copyin(g) - // CHECK: #pragma omp parallel for schedule(guided, argc) default(none) copyin(g) +#pragma omp parallel for schedule(guided, argc) default(none) copyin(g) linear(a) + // CHECK: #pragma omp parallel for schedule(guided, argc) default(none) copyin(g) linear(a) 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 for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered if (argc) num_threads(a) default(shared) shared(e) reduction(+ : h) +#pragma omp parallel for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered if (argc) num_threads(a) default(shared) shared(e) reduction(+ : h) linear(a:-5) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) foo(); - // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered if(argc) num_threads(a) default(shared) shared(e) reduction(+: h) - // CHECK-NEXT: for (int i = 0; i < 10; ++i) + // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered if(argc) num_threads(a) default(shared) shared(e) reduction(+: h) linear(a: -5) + // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) // CHECK-NEXT: foo(); return (tmain(argc) + tmain(argv[0][0])); diff --git a/test/OpenMP/parallel_for_firstprivate_messages.cpp b/test/OpenMP/parallel_for_firstprivate_messages.cpp index 2c762b49b3..1a9b0593b8 100644 --- a/test/OpenMP/parallel_for_firstprivate_messages.cpp +++ b/test/OpenMP/parallel_for_firstprivate_messages.cpp @@ -102,9 +102,6 @@ int foomain(int argc, char **argv) { #pragma omp parallel for firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp parallel for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}} - for (int k = 0; k < argc; ++k) - ++k; #pragma omp parallel { int v = 0; diff --git a/test/OpenMP/parallel_for_lastprivate_messages.cpp b/test/OpenMP/parallel_for_lastprivate_messages.cpp index 09bed02a05..cdc94964c9 100644 --- a/test/OpenMP/parallel_for_lastprivate_messages.cpp +++ b/test/OpenMP/parallel_for_lastprivate_messages.cpp @@ -104,9 +104,6 @@ int foomain(int argc, char **argv) { #pragma omp parallel for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp parallel for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}} - for (int k = 0; k < argc; ++k) - ++k; #pragma omp parallel { int v = 0; diff --git a/test/OpenMP/parallel_for_linear_codegen.cpp b/test/OpenMP/parallel_for_linear_codegen.cpp new file mode 100644 index 0000000000..7d27efef7b --- /dev/null +++ b/test/OpenMP/parallel_for_linear_codegen.cpp @@ -0,0 +1,261 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s +// expected-no-diagnostics +// REQUIRES: x86-registered-target +#ifndef HEADER +#define HEADER + +template +struct S { + T f; + S(T a) : f(a) {} + S() : f() {} + S &operator=(const S &); + operator T() { return T(); } + ~S() {} +}; + +volatile int g = 1212; +float f; +char cnt; + +// CHECK: [[S_FLOAT_TY:%.+]] = type { float } +// CHECK: [[CAP_MAIN_TY:%.+]] = type { float**, i64* } +// CHECK: [[S_INT_TY:%.+]] = type { i32 } +// CHECK: [[CAP_TMAIN_TY:%.+]] = type { i32**, i32* } +// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8* +// CHECK-DAG: [[F:@.+]] = global float 0.0 +// CHECK-DAG: [[CNT:@.+]] = global i8 0 +template +T tmain() { + S test; + T *pvar = &test.f; + T lvar = T(); +#pragma omp parallel for linear(pvar, lvar) + for (int i = 0; i < 2; ++i) { + ++pvar, ++lvar; + } + return T(); +} + +int main() { +#ifdef LAMBDA + // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212, + // LAMBDA-LABEL: @main + // LAMBDA: call void [[OUTER_LAMBDA:@.+]]( + [&]() { + // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]]( + // LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}}) +#pragma omp parallel for linear(g:5) + for (int i = 0; i < 2; ++i) { + // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: alloca i{{[0-9]+}}, + // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, + // LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], + // LAMBDA: store i32 0, + // LAMBDA: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}} + // LAMBDA: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]] + // LAMBDA: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) + // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]] + // LAMBDA: [[CNT:%.+]] = load i32, i32* + // LAMBDA: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5 + // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]] + // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]], + // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], 5 + // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** [[G_PRIVATE_ADDR_REF]] + // LAMBDA: call void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]]) + // LAMBDA: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]]) + g += 5; + // LAMBDA: call void @__kmpc_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]]) + [&]() { + // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]]) + // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]], + g = 2; + // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]] + // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]] + // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]] + }(); + } + }(); + return 0; +#elif defined(BLOCKS) + // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212, + // BLOCKS-LABEL: @main + // BLOCKS: call void {{%.+}}(i8 + ^{ + // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8* + // BLOCKS: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}}) +#pragma omp parallel for linear(g:5) + for (int i = 0; i < 2; ++i) { + // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: alloca i{{[0-9]+}}, + // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, + // BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], + // BLOCKS: store i32 0, + // BLOCKS: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}} + // BLOCKS: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]] + // BLOCKS: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) + // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]] + // BLOCKS: [[CNT:%.+]] = load i32, i32* + // BLOCKS: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5 + // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]] + // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]], + // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], 5 + // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]], + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]] + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: call void {{%.+}}(i8 + // BLOCKS: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]]) + g += 5; + // BLOCKS: call void @__kmpc_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]]) + g = 1; + ^{ + // BLOCKS: define {{.+}} void {{@.+}}(i8* + g = 2; + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: store i{{[0-9]+}} 2, i{{[0-9]+}}* + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} + // BLOCKS: ret + }(); + } + }(); + return 0; +#else + S test; + float *pvar = &test.f; + long long lvar = 0; +#pragma omp parallel for linear(pvar, lvar : 3) + for (int i = 0; i < 2; ++i) { + pvar += 3, lvar += 3; + } + return tmain(); +#endif +} + +// CHECK: define i{{[0-9]+}} @main() +// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]], +// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]]) +// CHECK: %{{.+}} = bitcast [[CAP_MAIN_TY]]* +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_MAIN_TY]]*)* [[MAIN_MICROTASK:@.+]] to void +// CHECK: = call {{.+}} [[TMAIN_INT:@.+]]() +// CHECK: call void [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]* +// CHECK: ret + +// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_MAIN_TY]]* %{{.+}}) +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_START:%.+]] = alloca float*, +// CHECK: [[LVAR_START:%.+]] = alloca i64, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_PRIV:%.+]] = alloca float*, +// CHECK: [[LVAR_PRIV:%.+]] = alloca i64, +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]] + +// Check for default initialization. +// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[PVAR_REF:%.+]] = load float**, float*** [[PVAR_PTR_REF]], +// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_REF]], +// CHECK: store float* [[PVAR_VAL]], float** [[PVAR_START]], +// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: [[LVAR_REF:%.+]] = load i64*, i64** [[LVAR_PTR_REF]], +// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_REF]], +// CHECK: store i64 [[LVAR_VAL]], i64* [[LVAR_START]], +// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) +// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3 +// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64 +// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 [[IDX]] +// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3 +// CHECK: [[CONV:%.+]] = sext i32 [[MUL]] to i64 +// CHECK: [[VAL:%.+]] = add nsw i64 [[LVAR_VAL]], [[CONV]] +// CHECK: store i64 [[VAL]], i64* [[LVAR_PRIV]], +// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_PRIV]] +// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 3 +// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_PRIV]], +// CHECK: [[ADD:%.+]] = add nsw i64 [[LVAR_VAL]], 3 +// CHECK: store i64 [[ADD]], i64* [[LVAR_PRIV]], +// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}}) +// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: ret void + +// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]() +// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]], +// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]]) +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_TMAIN_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void +// CHECK: call void [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]* +// CHECK: ret +// +// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_TMAIN_TY]]* %{{.+}}) +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_START:%.+]] = alloca i32*, +// CHECK: [[LVAR_START:%.+]] = alloca i32, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: alloca i{{[0-9]+}}, +// CHECK: [[PVAR_PRIV:%.+]] = alloca i32*, +// CHECK: [[LVAR_PRIV:%.+]] = alloca i32, +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]] + +// Check for default initialization. +// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0 +// CHECK: [[PVAR_REF:%.+]] = load i32**, i32*** [[PVAR_PTR_REF]], +// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_REF]], +// CHECK: store i32* [[PVAR_VAL]], i32** [[PVAR_START]], +// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1 +// CHECK: [[LVAR_REF:%.+]] = load i32*, i32** [[LVAR_PTR_REF]], +// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_REF]], +// CHECK: store i32 [[LVAR_VAL]], i32* [[LVAR_START]], +// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1) +// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1 +// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64 +// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i64 [[IDX]] +// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_START]], +// CHECK: [[CNT:%.+]] = load i32, i32* +// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1 +// CHECK: [[VAL:%.+]] = add nsw i32 [[LVAR_VAL]], [[MUL]] +// CHECK: store i32 [[VAL]], i32* [[LVAR_PRIV]], +// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_PRIV]] +// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i32 1 +// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]], +// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_PRIV]], +// CHECK: [[ADD:%.+]] = add nsw i32 [[LVAR_VAL]], 1 +// CHECK: store i32 [[ADD]], i32* [[LVAR_PRIV]], +// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}}) +// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK: ret void +#endif + diff --git a/test/OpenMP/parallel_for_linear_messages.cpp b/test/OpenMP/parallel_for_linear_messages.cpp new file mode 100644 index 0000000000..528fa27dca --- /dev/null +++ b/test/OpenMP/parallel_for_linear_messages.cpp @@ -0,0 +1,269 @@ +// RUN: %clang_cc1 -verify -fopenmp %s + +namespace X { +int x; +}; + +struct B { + static int ib; // expected-note {{'B::ib' declared here}} + static int bfoo() { return 8; } +}; + +int bfoo() { return 4; } + +int z; +const int C1 = 1; +const int C2 = 2; +void test_linear_colons() { + int B = 0; +#pragma omp parallel for linear(B : bfoo()) + for (int i = 0; i < 10; ++i) + ; +// expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'}} +#pragma omp parallel for linear(B::ib : B : bfoo()) + for (int i = 0; i < 10; ++i) + ; +// expected-error@+1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}} +#pragma omp parallel for linear(B : ib) + for (int i = 0; i < 10; ++i) + ; +// expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'?}} +#pragma omp parallel for linear(z : B : ib) + for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel for linear(B : B::bfoo()) + for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel for linear(X::x : ::z) + for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel for linear(B, ::z, X::x) + for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel for linear(::z) + for (int i = 0; i < 10; ++i) + ; +// expected-error@+1 {{expected variable name}} +#pragma omp parallel for linear(B::bfoo()) + for (int i = 0; i < 10; ++i) + ; +#pragma omp parallel for linear(B::ib, B : C1 + C2) + for (int i = 0; i < 10; ++i) + ; +} + +template +T test_template(T *arr, N num) { + N i; + T sum = (T)0; + T ind2 = -num * L; // expected-note {{'ind2' defined here}} +// expected-error@+1 {{argument of a linear clause should be of integral or pointer type}} +#pragma omp parallel for linear(ind2 : L) + for (i = 0; i < num; ++i) { + T cur = arr[(int)ind2]; + ind2 += L; + sum += cur; + } + return T(); +} + +template +int test_warn() { + int ind2 = 0; +// expected-warning@+1 {{zero linear step (ind2 should probably be const)}} +#pragma omp parallel for linear(ind2 : LEN) + for (int i = 0; i < 100; i++) { + ind2 += LEN; + } + return ind2; +} + +struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}} +extern S1 a; +class S2 { + mutable int a; + +public: + S2() : a(0) {} +}; +const S2 b; // expected-note 2 {{'b' defined here}} +const S2 ba[5]; +class S3 { + int a; + +public: + S3() : a(0) {} +}; +const S3 ca[5]; +class S4 { + int a; + S4(); + +public: + S4(int v) : a(v) {} +}; +class S5 { + int a; + S5() : a(0) {} + +public: + S5(int v) : a(v) {} +}; + +S3 h; +#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}} + +template +int foomain(I argc, C **argv) { + I e(4); + I g(5); + int i; + int &j = i; // expected-note {{'j' defined here}} +#pragma omp parallel for linear // expected-error {{expected '(' after 'linear'}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear() // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc : 5) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) + ++k; +// expected-error@+2 {{linear variable with incomplete type 'S1'}} +// expected-error@+1 {{const-qualified variable cannot be linear}} +#pragma omp parallel for linear(a, b : B::ib) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(e, g) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(i) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel + { + int v = 0; + int i; +#pragma omp parallel for linear(v : i) + for (int k = 0; k < argc; ++k) { + i = k; + v += i; + } + } +#pragma omp parallel for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type}} + for (int k = 0; k < argc; ++k) + ++k; + int v = 0; +#pragma omp parallel for linear(v : j) + for (int k = 0; k < argc; ++k) { + ++k; + v += j; + } +#pragma omp parallel for linear(i) + for (int k = 0; k < argc; ++k) + ++k; + return 0; +} + +namespace A { +double x; +#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}} +} +namespace C { +using A::x; +} + +int main(int argc, char **argv) { + double darr[100]; + // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}} + test_template<-4>(darr, 4); + // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}} + test_warn<0>(); + + S4 e(4); // expected-note {{'e' defined here}} + S5 g(5); // expected-note {{'g' defined here}} + int i; + int &j = i; // expected-note {{'j' defined here}} +#pragma omp parallel for linear // expected-error {{expected '(' after 'linear'}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear() // expected-error {{expected expression}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argc) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(S1) // expected-error {{'S1' does not refer to a value}} + for (int k = 0; k < argc; ++k) + ++k; +// expected-error@+2 {{linear variable with incomplete type 'S1'}} +// expected-error@+1 {{const-qualified variable cannot be linear}} +#pragma omp parallel for linear(a, b) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(argv[1]) // expected-error {{expected variable name}} + for (int k = 0; k < argc; ++k) + ++k; +// expected-error@+2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}} +// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}} +#pragma omp parallel for linear(e, g) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel + { + int i; +#pragma omp parallel for linear(i) + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(i : 4) + for (int k = 0; k < argc; ++k) { + ++k; + i += 4; + } + } +#pragma omp parallel for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type 'int &'}} + for (int k = 0; k < argc; ++k) + ++k; +#pragma omp parallel for linear(i) + for (int k = 0; k < argc; ++k) + ++k; + + foomain(argc, argv); + return 0; +} + diff --git a/test/OpenMP/parallel_for_loop_messages.cpp b/test/OpenMP/parallel_for_loop_messages.cpp index 8c0cdf8e9e..b33128a4a4 100644 --- a/test/OpenMP/parallel_for_loop_messages.cpp +++ b/test/OpenMP/parallel_for_loop_messages.cpp @@ -242,7 +242,6 @@ int test_iteration_spaces() { for (ii = 0; ii < 10; ii++) c[ii] = a[ii]; -// expected-error@+3 {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}} // expected-note@+2 {{defined as linear}} // expected-error@+2 {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be linear, predetermined as private}} #pragma omp parallel for linear(ii) diff --git a/test/OpenMP/parallel_for_misc_messages.c b/test/OpenMP/parallel_for_misc_messages.c index ee6f2e81bb..819f571d4e 100644 --- a/test/OpenMP/parallel_for_misc_messages.c +++ b/test/OpenMP/parallel_for_misc_messages.c @@ -59,11 +59,6 @@ void test_non_identifiers() { #pragma omp parallel for; for (i = 0; i < 16; ++i) ; -// expected-error@+2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}} -// expected-warning@+1 {{extra tokens at the end of '#pragma omp parallel for' are ignored}} -#pragma omp parallel for linear(x); - for (i = 0; i < 16; ++i) - ; // expected-warning@+1 {{extra tokens at the end of '#pragma omp parallel for' are ignored}} #pragma omp parallel for private(x);