diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index affa972529ea8..a0efd1675178a 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -394,6 +394,7 @@ OPENMP_FOR_SIMD_CLAUSE(linear) OPENMP_FOR_SIMD_CLAUSE(aligned) OPENMP_FOR_SIMD_CLAUSE(ordered) OPENMP_FOR_SIMD_CLAUSE(allocate) +OPENMP_FOR_SIMD_CLAUSE(if) // Clauses allowed for OpenMP directive 'omp sections'. OPENMP_SECTIONS_CLAUSE(private) diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index b1e623b861dec..eeeb8bef69bb2 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -485,6 +485,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, } break; case OMPD_for_simd: + if (OpenMPVersion < 50 && CKind == OMPC_if) + return false; switch (CKind) { #define OPENMP_FOR_SIMD_CLAUSE(Name) \ case OMPC_##Name: \ diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 476d380139dfe..e2c055f549e02 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1796,6 +1796,39 @@ static LValue EmitOMPHelperVar(CodeGenFunction &CGF, return CGF.EmitLValue(Helper); } +static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, + const RegionCodeGenTy &SimdInitGen, + const RegionCodeGenTy &BodyCodeGen) { + auto &&ThenGen = [&SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF, + PrePostActionTy &) { + CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); + SimdInitGen(CGF); + + BodyCodeGen(CGF); + }; + auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) { + CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); + CGF.LoopStack.setVectorizeEnable(/*Enable=*/false); + + BodyCodeGen(CGF); + }; + const Expr *IfCond = nullptr; + for (const auto *C : S.getClausesOfKind()) { + if (CGF.getLangOpts().OpenMP >= 50 && + (C->getNameModifier() == OMPD_unknown || + C->getNameModifier() == OMPD_simd)) { + IfCond = C->getCondition(); + break; + } + } + if (IfCond) { + CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen); + } else { + RegionCodeGenTy ThenRCG(ThenGen); + ThenRCG(CGF); + } +} + static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action) { Action.Enter(CGF); @@ -1859,45 +1892,20 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - auto &&ThenGen = [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { - CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); - CGF.EmitOMPSimdInit(S); - - CGF.EmitOMPInnerLoop( - S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest()); - CGF.EmitStopPoint(&S); - }, - [](CodeGenFunction &) {}); - }; - auto &&ElseGen = [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { - CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); - CGF.LoopStack.setVectorizeEnable(/*Enable=*/false); - - CGF.EmitOMPInnerLoop( - S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest()); - CGF.EmitStopPoint(&S); - }, - [](CodeGenFunction &) {}); - }; - const Expr *IfCond = nullptr; - for (const auto *C : S.getClausesOfKind()) { - if (CGF.getLangOpts().OpenMP >= 50 && - (C->getNameModifier() == OMPD_unknown || - C->getNameModifier() == OMPD_simd)) { - IfCond = C->getCondition(); - break; - } - } - if (IfCond) { - CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen); - } else { - RegionCodeGenTy ThenRCG(ThenGen); - ThenRCG(CGF); - } + emitCommonSimdLoop( + CGF, S, + [&S](CodeGenFunction &CGF, PrePostActionTy &) { + CGF.EmitOMPSimdInit(S); + }, + [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { + CGF.EmitOMPInnerLoop( + S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), + [&S](CodeGenFunction &CGF) { + CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest()); + CGF.EmitStopPoint(&S); + }, + [](CodeGenFunction &) {}); + }); CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; }); // Emit final copy of the lastprivate variables at the end of loops. if (HasLastprivateClause) @@ -1982,27 +1990,32 @@ void CodeGenFunction::EmitOMPOuterLoop( JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc"); BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); - // Generate !llvm.loop.parallel metadata for loads and stores for loops - // with dynamic/guided scheduling and without ordered clause. - if (!isOpenMPSimdDirective(S.getDirectiveKind())) - LoopStack.setParallel(!IsMonotonic); - else - EmitOMPSimdInit(S, IsMonotonic); - - SourceLocation Loc = S.getBeginLoc(); - - // when 'distribute' is not combined with a 'for': - // while (idx <= UB) { BODY; ++idx; } - // when 'distribute' is combined with a 'for' - // (e.g. 'distribute parallel for') - // while (idx <= UB) { ; idx += ST; } - EmitOMPInnerLoop( - S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr, - [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { - CodeGenLoop(CGF, S, LoopExit); + emitCommonSimdLoop( + *this, S, + [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) { + // Generate !llvm.loop.parallel metadata for loads and stores for loops + // with dynamic/guided scheduling and without ordered clause. + if (!isOpenMPSimdDirective(S.getDirectiveKind())) + CGF.LoopStack.setParallel(!IsMonotonic); + else + CGF.EmitOMPSimdInit(S, IsMonotonic); }, - [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) { - CodeGenOrdered(CGF, Loc, IVSize, IVSigned); + [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered, + &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { + SourceLocation Loc = S.getBeginLoc(); + // when 'distribute' is not combined with a 'for': + // while (idx <= UB) { BODY; ++idx; } + // when 'distribute' is combined with a 'for' + // (e.g. 'distribute parallel for') + // while (idx <= UB) { ; idx += ST; } + CGF.EmitOMPInnerLoop( + S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr, + [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { + CodeGenLoop(CGF, S, LoopExit); + }, + [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) { + CodeGenOrdered(CGF, Loc, IVSize, IVSigned); + }); }); EmitBlock(Continue.getBlock()); @@ -2491,47 +2504,58 @@ bool CodeGenFunction::EmitOMPWorksharingLoop( /* Chunked */ Chunk != nullptr) || StaticChunkedOne) && !Ordered) { - if (isOpenMPSimdDirective(S.getDirectiveKind())) - EmitOMPSimdInit(S, /*IsMonotonic=*/true); - // OpenMP [2.7.1, Loop Construct, Description, table 2-1] - // When no chunk_size is specified, the iteration space is divided into - // chunks that are approximately equal in size, and at most one chunk is - // distributed to each thread. Note that the size of the chunks is - // unspecified in this case. - CGOpenMPRuntime::StaticRTInput StaticInit( - IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(), - UB.getAddress(), ST.getAddress(), - StaticChunkedOne ? Chunk : nullptr); - RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(), - ScheduleKind, StaticInit); JumpDest LoopExit = getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); - // UB = min(UB, GlobalUB); - if (!StaticChunkedOne) - EmitIgnoredExpr(S.getEnsureUpperBound()); - // IV = LB; - EmitIgnoredExpr(S.getInit()); - // For unchunked static schedule generate: - // - // while (idx <= UB) { - // BODY; - // ++idx; - // } - // - // For static schedule with chunk one: - // - // while (IV <= PrevUB) { - // BODY; - // IV += ST; - // } - EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), - StaticChunkedOne ? S.getCombinedParForInDistCond() : S.getCond(), - StaticChunkedOne ? S.getDistInc() : S.getInc(), - [&S, LoopExit](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, LoopExit); - CGF.EmitStopPoint(&S); + emitCommonSimdLoop( + *this, S, + [&S](CodeGenFunction &CGF, PrePostActionTy &) { + if (isOpenMPSimdDirective(S.getDirectiveKind())) + CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true); }, - [](CodeGenFunction &) {}); + [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk, + &S, ScheduleKind, LoopExit, + &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { + // OpenMP [2.7.1, Loop Construct, Description, table 2-1] + // When no chunk_size is specified, the iteration space is divided + // into chunks that are approximately equal in size, and at most + // one chunk is distributed to each thread. Note that the size of + // the chunks is unspecified in this case. + CGOpenMPRuntime::StaticRTInput StaticInit( + IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(), + UB.getAddress(), ST.getAddress(), + StaticChunkedOne ? Chunk : nullptr); + CGF.CGM.getOpenMPRuntime().emitForStaticInit( + CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, + StaticInit); + // UB = min(UB, GlobalUB); + if (!StaticChunkedOne) + CGF.EmitIgnoredExpr(S.getEnsureUpperBound()); + // IV = LB; + CGF.EmitIgnoredExpr(S.getInit()); + // For unchunked static schedule generate: + // + // while (idx <= UB) { + // BODY; + // ++idx; + // } + // + // For static schedule with chunk one: + // + // while (IV <= PrevUB) { + // BODY; + // IV += ST; + // } + CGF.EmitOMPInnerLoop( + S, LoopScope.requiresCleanups(), + StaticChunkedOne ? S.getCombinedParForInDistCond() + : S.getCond(), + StaticChunkedOne ? S.getDistInc() : S.getInc(), + [&S, LoopExit](CodeGenFunction &CGF) { + CGF.EmitOMPLoopBody(S, LoopExit); + CGF.EmitStopPoint(&S); + }, + [](CodeGenFunction &) {}); + }); EmitBlock(LoopExit.getBlock()); // Tell the runtime we are done. auto &&CodeGen = [&S](CodeGenFunction &CGF) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7ced9eea75e0f..1ff25e7eb47ff 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4498,6 +4498,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_for_simd: Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_sections: Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, @@ -10670,6 +10672,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop_simd: case OMPD_target_data: case OMPD_simd: + case OMPD_for_simd: // Do not capture if-clause expressions. break; case OMPD_threadprivate: @@ -10687,7 +10690,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_end_declare_target: case OMPD_teams: case OMPD_for: - case OMPD_for_simd: case OMPD_sections: case OMPD_section: case OMPD_single: diff --git a/clang/test/OpenMP/for_simd_ast_print.cpp b/clang/test/OpenMP/for_simd_ast_print.cpp index d626994bf8b6c..45d8f699a48d6 100644 --- a/clang/test/OpenMP/for_simd_ast_print.cpp +++ b/clang/test/OpenMP/for_simd_ast_print.cpp @@ -1,10 +1,16 @@ -// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP45 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP45 +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -fopenmp-version=50 -DOMP5 +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 -// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP45 // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP45 +// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -fopenmp-version=50 -DOMP5 +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 // expected-no-diagnostics #ifndef HEADER @@ -46,7 +52,7 @@ class S8 : public S7 { public: S8(int v) : S7(v){ -#pragma omp for simd private(a) private(this->a) private(S7::a) +#pragma omp for simd private(a) private(this->a) private(S7::a) for (int k = 0; k < a.a; ++k) ++this->a.a; } @@ -90,8 +96,13 @@ template struct S { // CHECK: T res; // CHECK: T val; // CHECK: T lin = 0; +#ifdef OMP5 + #pragma omp for simd private(val) safelen(7) linear(lin : -5) lastprivate(res) simdlen(5) allocate(res) if(res) +#else #pragma omp for simd private(val) safelen(7) linear(lin : -5) lastprivate(res) simdlen(5) allocate(res) -// CHECK-NEXT: #pragma omp for simd private(val) safelen(7) linear(lin: -5) lastprivate(res) simdlen(5) +#endif +// OMP50-NEXT: #pragma omp for simd private(val) safelen(7) linear(lin: -5) lastprivate(res) simdlen(5) allocate(res) if(res) +// OMP45-NEXT: #pragma omp for simd private(val) safelen(7) linear(lin: -5) lastprivate(res) simdlen(5) allocate(res) for (T i = 7; i < m_a; ++i) { val = v[i-7] + m_a; res = val; @@ -169,8 +180,13 @@ int main (int argc, char **argv) { // CHECK-NEXT: foo(); const int CLEN = 4; // CHECK-NEXT: const int CLEN = 4; +#ifdef OMP5 + #pragma omp for simd aligned(a:CLEN) linear(a:CLEN) safelen(CLEN) collapse( 1 ) simdlen(CLEN) if(simd:a) +#else #pragma omp for simd aligned(a:CLEN) linear(a:CLEN) safelen(CLEN) collapse( 1 ) simdlen(CLEN) -// CHECK-NEXT: #pragma omp for simd aligned(a: CLEN) linear(a: CLEN) safelen(CLEN) collapse(1) simdlen(CLEN) +#endif +// OMP50-NEXT: #pragma omp for simd aligned(a: CLEN) linear(a: CLEN) safelen(CLEN) collapse(1) simdlen(CLEN) if(simd: a) +// OMP45-NEXT: #pragma omp for simd aligned(a: CLEN) linear(a: CLEN) safelen(CLEN) collapse(1) simdlen(CLEN) for (int i = 0; i < 10; ++i)foo(); // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: foo(); diff --git a/clang/test/OpenMP/for_simd_codegen.cpp b/clang/test/OpenMP/for_simd_codegen.cpp index c36f52704b7c5..4bc6b362f0278 100644 --- a/clang/test/OpenMP/for_simd_codegen.cpp +++ b/clang/test/OpenMP/for_simd_codegen.cpp @@ -1,12 +1,20 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - < %s | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP45 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t < %s -// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -emit-llvm -o - < %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -emit-llvm -o - < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP45 // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm -o - < %s | FileCheck %s --check-prefix=TERM_DEBUG +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - < %s -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t < %s -fopenmp-version=50 -DOMP5 +// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -emit-llvm -o - -fopenmp-version=50 -DOMP5 < %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm -o - < %s -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=TERM_DEBUG // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t < %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -emit-llvm -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm -fexceptions -fcxx-exceptions -o - < %s -fopenmp-version=50 -DOMP5 | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t < %s -fopenmp-version=50 -DOMP5 +// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -debug-info-kind=limited -std=c++11 -include-pch %t -verify -fopenmp-version=50 -DOMP5 -emit-llvm -o - < %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm -o - < %s -fopenmp-version=50 -DOMP5 | FileCheck --check-prefix SIMD-ONLY0 %s // SIMD-ONLY0-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics #ifndef HEADER @@ -17,7 +25,11 @@ double *g_ptr; // CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}}) void simple(float *a, float *b, float *c, float *d) { +#ifdef OMP5 + #pragma omp for simd if (true) +#else #pragma omp for simd +#endif // CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i32* [[LB:%[^,]+]], i32* [[UB:%[^,]+]], i32* [[STRIDE:%[^,]+]], i32 1, i32 1) // CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]], // CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 5 @@ -316,7 +328,15 @@ void simple(float *a, float *b, float *c, float *d) { // CHECK: store i32 -1, i32* [[R:%[^,]+]], R = -1; // CHECK: store i32 1, i32* [[R_PRIV:%[^,]+]], +// OMP50: [[A_VAL:%.+]] = load i32, i32* % +// OMP50: [[COND:%.+]] = icmp ne i32 [[A_VAL]], 0 +// OMP50: br i1 [[COND]], label {{%?}}[[THEN:[^,]+]], label {{%?}}[[ELSE:[^,]+]] +// OMP50: [[THEN]]: +#ifdef OMP5 + #pragma omp for simd reduction(*:R) if (simd:A) +#else #pragma omp for simd reduction(*:R) +#endif // CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1) // CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]], // CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6 @@ -351,8 +371,48 @@ void simple(float *a, float *b, float *c, float *d) { // CHECK: [[IV8_2:%.+]] = load i64, i64* [[OMP_IV8]] // CHECK-NEXT: [[ADD8_2:%.+]] = add nsw i64 [[IV8_2]], 1 // CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]] +// CHECK-NEXT: br label {{%?}}[[SIMD_LOOP8_COND]], {{.*}}!llvm.loop ![[SIMD_LOOP:.+]] } // CHECK: [[SIMPLE_LOOP8_END]]: +// OMP50: br label {{%?}}[[IF_EXIT:[^,]+]] +// OMP50: [[ELSE]]: +// OMP50: call void @__kmpc_for_static_init_8(%struct.ident_t* {{[^,]+}}, i32 %{{[^,]+}}, i32 34, i32* %{{[^,]+}}, i64* [[LB:%[^,]+]], i64* [[UB:%[^,]+]], i64* [[STRIDE:%[^,]+]], i64 1, i64 1) +// OMP50: [[UB_VAL:%.+]] = load i64, i64* [[UB]], +// OMP50: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6 +// OMP50: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]] +// OMP50: [[TRUE]]: +// OMP50: br label %[[SWITCH:[^,]+]] +// OMP50: [[FALSE]]: +// OMP50: [[UB_VAL:%.+]] = load i64, i64* [[UB]], +// OMP50: br label %[[SWITCH]] +// OMP50: [[SWITCH]]: +// OMP50: [[UP:%.+]] = phi i64 [ 6, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ] +// OMP50: store i64 [[UP]], i64* [[UB]], +// OMP50: [[LB_VAL:%.+]] = load i64, i64* [[LB]], +// OMP50: store i64 [[LB_VAL]], i64* [[OMP_IV8:%[^,]+]], + +// OMP50: br label %[[SIMD_LOOP8_COND:[^,]+]] +// OMP50: [[SIMD_LOOP8_COND]]: +// OMP50-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]] +// OMP50-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]] +// OMP50-NEXT: [[CMP8:%.+]] = icmp sle i64 [[IV8]], [[UB_VAL]] +// OMP50-NEXT: br i1 [[CMP8]], label %[[SIMPLE_LOOP8_BODY:.+]], label %[[SIMPLE_LOOP8_END:[^,]+]] +// OMP50: [[SIMPLE_LOOP8_BODY]]: +// Start of body: calculate i from IV: +// OMP50: [[IV8_0:%.+]] = load i64, i64* [[OMP_IV8]] +// OMP50-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV8_0]], 3 +// OMP50-NEXT: [[LC_IT_2:%.+]] = add nsw i64 -10, [[LC_IT_1]] +// OMP50-NEXT: store i64 [[LC_IT_2]], i64* [[LC:%[^,]+]], +// OMP50-NEXT: [[LC_VAL:%.+]] = load i64, i64* [[LC]] +// OMP50: store i32 %{{.+}}, i32* [[R_PRIV]], +// OMP50: [[IV8_2:%.+]] = load i64, i64* [[OMP_IV8]] +// OMP50-NEXT: [[ADD8_2:%.+]] = add nsw i64 [[IV8_2]], 1 +// OMP50-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]] +// OMP50-NEXT: br label {{%?}}[[SIMD_LOOP8_COND]], {{.*}}!llvm.loop ![[NOSIMD_LOOP:.+]] +// OMP50: [[SIMPLE_LOOP8_END]]: +// OMP50: br label {{%?}}[[IF_EXIT]] +// OMP50: [[IF_EXIT]]: + // CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 %{{.+}}) // CHECK: call i32 @__kmpc_reduce( // CHECK: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]], @@ -742,4 +802,10 @@ void parallel_simd(float *a) { } // TERM_DEBUG: !{{[0-9]+}} = !DILocation(line: [[@LINE-11]], // TERM_DEBUG-NOT: line: 0, +// OMP45-NOT: !"llvm.loop.vectorize.enable", i1 false +// CHECK-DAG: ![[SIMD_LOOP]] = distinct !{![[SIMD_LOOP]], {{.*}}![[VECT_LOOP:[^,]+]]} +// CHECK-DAG: ![[VECT_LOOP]] = !{!"llvm.loop.vectorize.enable", i1 true} +// OMP45-NOT: !"llvm.loop.vectorize.enable", i1 false +// OMP50-DAG: ![[NOSIMD_LOOP]] = distinct !{![[NOSIMD_LOOP]], {{.*}}![[NOVECT_LOOP:[^,]+]]} +// OMP50-DAG: ![[NOVECT_LOOP]] = !{!"llvm.loop.vectorize.enable", i1 false} #endif // HEADER diff --git a/clang/test/OpenMP/for_simd_if_messages.cpp b/clang/test/OpenMP/for_simd_if_messages.cpp new file mode 100644 index 0000000000000..6dd9dd30871e2 --- /dev/null +++ b/clang/test/OpenMP/for_simd_if_messages.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -Wuninitialized + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 %s -Wuninitialized + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp for simd if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + +struct S1; // expected-note {{declared here}} + +template // expected-note {{declared here}} +int tmain(T argc, S **argv) { + T z; + int i; + #pragma omp for simd if // expected-error {{expected '(' after 'if'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp for simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc > 0 ? argv[1] : argv[2]) + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp for simd' cannot contain more than one 'if' clause}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (S) // expected-error {{'S' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(argc + z) + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc) + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(target : argc) // expected-error {{directive name modifier 'target' is not allowed for '#pragma omp for simd'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc) if (simd :argc) // expected-error {{directive '#pragma omp for simd' cannot contain more than one 'if' clause with 'simd' name modifier}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}} + for (i = 0; i < argc; ++i) foo(); + + return 0; +} + +int main(int argc, char **argv) { + int i, z; + #pragma omp for simd if // expected-error {{expected '(' after 'if'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp for simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc > 0 ? argv[1] : argv[2]) + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp for simd' cannot contain more than one 'if' clause}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc + z) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp for simd'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc) if (simd :argc) // expected-error {{directive '#pragma omp for simd' cannot contain more than one 'if' clause with 'simd' name modifier}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp for simd if(simd : argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}} + for (i = 0; i < argc; ++i) foo(); + + return tmain(argc, argv); +}