[OPENMP 4.1] Support for 'linear' clause in loop directives.
OpenMP 4.1 allows 'linear' clause in loop directives. Patch adds support for it. llvm-svn: 243969
This commit is contained in:
parent
323dc2d064
commit
54acd40591
|
@ -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)
|
||||
|
|
|
@ -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<OMPLinearClause>(C))
|
||||
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(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<OMPLinearClause>(C))
|
||||
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
|
||||
B.NumIterations, *this, CurScope))
|
||||
return StmtError();
|
||||
}
|
||||
}
|
||||
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
|
||||
NestedLoopCount, Clauses, AStmt, B);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <class T>
|
||||
struct S {
|
||||
T f;
|
||||
S(T a) : f(a) {}
|
||||
S() : f() {}
|
||||
S<T> &operator=(const S<T> &);
|
||||
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 <typename T>
|
||||
T tmain() {
|
||||
S<T> 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<float> 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<int>();
|
||||
#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
|
||||
|
|
@ -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<int L, class T, class N> 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 LEN> 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<class I, class C> 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<int,char>(argc,argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
;
|
||||
|
|
|
@ -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<int, 5>(argc) + tmain<char, 1>(argv[0][0]));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <class T>
|
||||
struct S {
|
||||
T f;
|
||||
S(T a) : f(a) {}
|
||||
S() : f() {}
|
||||
S<T> &operator=(const S<T> &);
|
||||
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 <typename T>
|
||||
T tmain() {
|
||||
S<T> 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<float> 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<int>();
|
||||
#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
|
||||
|
|
@ -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 <int L, class T, class N>
|
||||
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 LEN>
|
||||
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 <class I, class C>
|
||||
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<int, char>(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue