From d08c056695a59fb1cfc7ccc9a2784bb9a6514551 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 19 Nov 2019 12:07:54 -0500 Subject: [PATCH] [OPENMP50]Add if clause in simd directive. According to OpenMP 5.0, if clause can be used in simd directive. If condition in the if clause if false, the non-vectorized version of the loop must be executed. --- clang/include/clang/ASTMatchers/ASTMatchers.h | 4 +- clang/include/clang/Basic/OpenMPKinds.def | 1 + clang/include/clang/Basic/OpenMPKinds.h | 3 +- clang/lib/Basic/OpenMPKinds.cpp | 5 +- clang/lib/CodeGen/CGOpenMPRuntime.h | 22 ++-- clang/lib/CodeGen/CGStmtOpenMP.cpp | 49 +++++++-- clang/lib/CodeGen/CodeGenFunction.h | 13 +++ clang/lib/Parse/ParseOpenMP.cpp | 3 +- clang/lib/Sema/SemaOpenMP.cpp | 4 +- clang/test/OpenMP/simd_ast_print.cpp | 28 +++-- clang/test/OpenMP/simd_codegen.cpp | 46 +++++++- clang/test/OpenMP/simd_if_messages.cpp | 101 ++++++++++++++++++ 12 files changed, 246 insertions(+), 33 deletions(-) create mode 100644 clang/test/OpenMP/simd_if_messages.cpp diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 72ae63f9a757..3a5d0c08337e 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -6781,7 +6781,9 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) { /// ``isAllowedToContainClauseKind("OMPC_default").`` AST_MATCHER_P(OMPExecutableDirective, isAllowedToContainClauseKind, OpenMPClauseKind, CKind) { - return isAllowedClauseForDirective(Node.getDirectiveKind(), CKind); + return isAllowedClauseForDirective( + Node.getDirectiveKind(), CKind, + Finder->getASTContext().getLangOpts().OpenMP); } //----------------------------------------------------------------------------// diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 9bba5e6b96ba..affa972529ea 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -366,6 +366,7 @@ OPENMP_SIMD_CLAUSE(simdlen) OPENMP_SIMD_CLAUSE(collapse) OPENMP_SIMD_CLAUSE(reduction) OPENMP_SIMD_CLAUSE(allocate) +OPENMP_SIMD_CLAUSE(if) // Clauses allowed for directive 'omp for'. OPENMP_FOR_CLAUSE(private) diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index 208e360c8a70..121c8bd2e48b 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -219,7 +219,8 @@ unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str); const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type); bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, - OpenMPClauseKind CKind); + OpenMPClauseKind CKind, + unsigned OpenMPVersion); /// Checks if the specified directive is a directive with an associated /// loop construct. diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 4e6c677f11db..b1e623b861de 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -447,7 +447,8 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, } bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, - OpenMPClauseKind CKind) { + OpenMPClauseKind CKind, + unsigned OpenMPVersion) { assert(DKind <= OMPD_unknown); assert(CKind <= OMPC_unknown); switch (DKind) { @@ -462,6 +463,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, } break; case OMPD_simd: + if (OpenMPVersion < 50 && CKind == OMPC_if) + return false; switch (CKind) { #define OPENMP_SIMD_CLAUSE(Name) \ case OMPC_##Name: \ diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index d051170121ca..d806c27fdcba 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -241,17 +241,6 @@ protected: bool IsOffloadEntry, const RegionCodeGenTy &CodeGen); - /// Emits code for OpenMP 'if' clause using specified \a CodeGen - /// function. Here is the logic: - /// if (Cond) { - /// ThenGen(); - /// } else { - /// ElseGen(); - /// } - void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, - const RegionCodeGenTy &ThenGen, - const RegionCodeGenTy &ElseGen); - /// Emits object of ident_t type with info for source location. /// \param Flags Flags for OpenMP location. /// @@ -819,6 +808,17 @@ public: virtual ~CGOpenMPRuntime() {} virtual void clear(); + /// Emits code for OpenMP 'if' clause using specified \a CodeGen + /// function. Here is the logic: + /// if (Cond) { + /// ThenGen(); + /// } else { + /// ElseGen(); + /// } + void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, + const RegionCodeGenTy &ThenGen, + const RegionCodeGenTy &ElseGen); + /// Checks if the \p Body is the \a CompoundStmt and returns its child /// statement iff there is only one that is not evaluatable at the compile /// time. diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 4406fbc4144b..476d380139df 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1846,8 +1846,6 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, CGF.EmitIgnoredExpr(S.getCalcLastIteration()); } - CGF.EmitOMPSimdInit(S); - emitAlignedClause(CGF, S); (void)CGF.EmitOMPLinearClauseInit(S); { @@ -1860,13 +1858,46 @@ static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, (void)LoopScope.Privatize(); if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); - CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), - S.getInc(), - [&S](CodeGenFunction &CGF) { - CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest()); - CGF.EmitStopPoint(&S); - }, - [](CodeGenFunction &) {}); + + 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); + } CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; }); // Emit final copy of the lastprivate variables at the end of loops. if (HasLastprivateClause) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 5c3d1764fad7..7a2627ccf58b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -947,6 +947,19 @@ public: } }; + /// Save/restore original map of previously emitted local vars in case when we + /// need to duplicate emission of the same code several times in the same + /// function for OpenMP code. + class OMPLocalDeclMapRAII { + CodeGenFunction &CGF; + DeclMapTy SavedMap; + + public: + OMPLocalDeclMapRAII(CodeGenFunction &CGF) + : CGF(CGF), SavedMap(CGF.LocalDeclMap) {} + ~OMPLocalDeclMapRAII() { SavedMap.swap(CGF.LocalDeclMap); } + }; + /// Takes the old cleanup stack size and emits the cleanup blocks /// that have been added. void diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 5b95dbbdea6d..208e3247a8be 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1939,7 +1939,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, bool ErrorFound = false; bool WrongDirective = false; // Check if clause is allowed for the given directive. - if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { + if (CKind != OMPC_unknown && + !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); ErrorFound = true; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index d0f2e7c30ae6..7ced9eea75e0 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4488,6 +4488,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_simd: Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_for: Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, @@ -10667,6 +10669,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_target_data: + case OMPD_simd: // Do not capture if-clause expressions. break; case OMPD_threadprivate: @@ -10683,7 +10686,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_teams: - case OMPD_simd: case OMPD_for: case OMPD_for_simd: case OMPD_sections: diff --git a/clang/test/OpenMP/simd_ast_print.cpp b/clang/test/OpenMP/simd_ast_print.cpp index dcd5d7f2dc8d..c538924e93c4 100644 --- a/clang/test/OpenMP/simd_ast_print.cpp +++ b/clang/test/OpenMP/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 -fopenmp-version=50 -ast-print %s -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -DOMP5 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -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 -fopenmp-version=50 -ast-print %s -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -DOMP5 +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 // expected-no-diagnostics #ifndef HEADER @@ -157,10 +163,15 @@ int main (int argc, char **argv) { for (int i=0; i < 2; ++i)*a=2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: *a = 2; +#ifdef OMP5 +#pragma omp simd private(argc, b),lastprivate(d,f) collapse(2) aligned(a : 4) if(simd:a) +// OMP50-NEXT: #pragma omp simd private(argc,b) lastprivate(d,f) collapse(2) aligned(a: 4) if(simd: a) +#else #pragma omp simd private(argc, b),lastprivate(d,f) collapse(2) aligned(a : 4) +// OMP45-NEXT: #pragma omp simd private(argc,b) lastprivate(d,f) collapse(2) aligned(a: 4) +#endif // OMP5 for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) {foo(); k1 += 8; k2 += 8;} -// CHECK-NEXT: #pragma omp simd private(argc,b) lastprivate(d,f) collapse(2) aligned(a: 4) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) { // CHECK-NEXT: foo(); @@ -172,8 +183,13 @@ int main (int argc, char **argv) { // CHECK-NEXT: foo(); const int CLEN = 4; // CHECK-NEXT: const int CLEN = 4; +#ifdef OMP5 + #pragma omp simd aligned(a:CLEN) linear(a:CLEN) safelen(CLEN) collapse( 1 ) simdlen(CLEN) linear(val(ref): CLEN) if(a) +// OMP50-NEXT: #pragma omp simd aligned(a: CLEN) linear(a: CLEN) safelen(CLEN) collapse(1) simdlen(CLEN) linear(val(ref): CLEN) if(a) +#else #pragma omp simd aligned(a:CLEN) linear(a:CLEN) safelen(CLEN) collapse( 1 ) simdlen(CLEN) linear(val(ref): CLEN) -// CHECK-NEXT: #pragma omp simd aligned(a: CLEN) linear(a: CLEN) safelen(CLEN) collapse(1) simdlen(CLEN) linear(val(ref): CLEN) +// OMP45-NEXT: #pragma omp simd aligned(a: CLEN) linear(a: CLEN) safelen(CLEN) collapse(1) simdlen(CLEN) linear(val(ref): CLEN) +#endif // OMP5 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/simd_codegen.cpp b/clang/test/OpenMP/simd_codegen.cpp index 8a636fba231f..19ed323af426 100644 --- a/clang/test/OpenMP/simd_codegen.cpp +++ b/clang/test/OpenMP/simd_codegen.cpp @@ -2,11 +2,17 @@ // 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 %s -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fexceptions -fcxx-exceptions -debug-info-kind=line-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -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 %s -emit-llvm -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %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 %s -emit-llvm -o - | FileCheck %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 %s -o - | FileCheck --check-prefix=TERM_DEBUG %s +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 +// 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 %s -emit-llvm -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 // expected-no-diagnostics #ifndef HEADER #define HEADER @@ -18,8 +24,12 @@ 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 simd if (simd: true) +#else #pragma omp simd -// CHECK: store i32 0, i32* [[OMP_IV:%[^,]+]] +#endif + // CHECK: store i32 0, i32* [[OMP_IV:%[^,]+]] // CHECK: [[IV:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.access.group // CHECK-NEXT: [[CMP:%.+]] = icmp slt i32 [[IV]], 6 @@ -221,7 +231,16 @@ void simple(float *a, float *b, float *c, float *d) { R = -1; // CHECK: store i64 0, i64* [[OMP_IV8:%[^,]+]], // CHECK: store i32 1, i32* [[R_PRIV:%[^,]+]], +#ifdef OMP5 + #pragma omp simd reduction(*:R) if(A) +#else #pragma omp simd reduction(*:R) +#endif +// OMP50: [[A_VAL:%.+]] = load i32, i32* [[A]], +// OMP50-NEXT: [[COND:%.+]] = icmp ne i32 [[A_VAL]], 0 +// OMP50-NEXT: br i1 [[COND]], label {{%?}}[[THEN:[^,]+]], label {{%?}}[[ELSE:[^,]+]] +// OMP50: [[THEN]]: + // CHECK: br label %[[SIMD_LOOP8_COND:[^,]+]] // CHECK: [[SIMD_LOOP8_COND]]: // CHECK-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.access.group @@ -242,6 +261,28 @@ void simple(float *a, float *b, float *c, float *d) { // CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]{{.*}}!llvm.access.group } // CHECK: [[SIMPLE_LOOP8_END]]: +// OMP50: br label {{%?}}[[EXIT:[^,]+]] +// OMP50: br label %[[SIMD_LOOP8_COND:[^,]+]] +// OMP50: [[SIMD_LOOP8_COND]]: +// OMP50-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]],{{[^!]*}} +// OMP50-NEXT: [[CMP8:%.+]] = icmp slt i64 [[IV8]], 7 +// 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: br label {{%?}}[[SIMD_LOOP8_COND]], {{.*}}!llvm.loop ![[DISABLE_VECT:.+]] +// OMP50: [[SIMPLE_LOOP8_END]]: +// OMP50: br label {{%?}}[[EXIT]] +// OMP50: [[EXIT]]: + // CHECK-DAG: [[R_VAL:%.+]] = load i32, i32* [[R]], // CHECK-DAG: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]], // CHECK: [[RED:%.+]] = mul nsw i32 [[R_VAL]], [[R_PRIV_VAL]] @@ -761,6 +802,7 @@ S8 s8(0); // TERM_DEBUG-NOT: line: 0, // TERM_DEBUG: distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_simd_codegen.cpp", - +// OMP50-DAG: ![[NOVECT:.+]] = !{!"llvm.loop.vectorize.enable", i1 false} +// OMP50-DAG: ![[DISABLE_VECT]] = distinct !{{.*}}![[NOVECT]]{{[,}]}} #endif // HEADER diff --git a/clang/test/OpenMP/simd_if_messages.cpp b/clang/test/OpenMP/simd_if_messages.cpp new file mode 100644 index 000000000000..9af63414142c --- /dev/null +++ b/clang/test/OpenMP/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 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 simd if // expected-error {{expected '(' after 'if'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc > 0 ? argv[1] : argv[2]) + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp simd' cannot contain more than one 'if' clause}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (S) // expected-error {{'S' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(argc + z) + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : argc) + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(target : argc) // expected-error {{directive name modifier 'target' is not allowed for '#pragma omp simd'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : argc) if (simd :argc) // expected-error {{directive '#pragma omp simd' cannot contain more than one 'if' clause with 'simd' name modifier}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp 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 simd if // expected-error {{expected '(' after 'if'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if () // expected-error {{expected expression}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc > 0 ? argv[1] : argv[2]) + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp simd' cannot contain more than one 'if' clause}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (S1) // expected-error {{'S1' does not refer to a value}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp 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 simd if(simd : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : argc + z) if (target:argc) // expected-error {{directive name modifier 'target' is not allowed for '#pragma omp simd'}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp simd if(simd : argc) if (simd :argc) // expected-error {{directive '#pragma omp simd' cannot contain more than one 'if' clause with 'simd' name modifier}} + for (i = 0; i < argc; ++i) foo(); + #pragma omp 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); +}