Author: Alexey Bataev
Date: 2019-11-19T15:58:19-05:00
New Revision: d08c056695a59fb1cfc7ccc9a2784bb9a6514551

URL: 
https://github.com/llvm/llvm-project/commit/d08c056695a59fb1cfc7ccc9a2784bb9a6514551
DIFF: 
https://github.com/llvm/llvm-project/commit/d08c056695a59fb1cfc7ccc9a2784bb9a6514551.diff

LOG: [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.

Added: 
    clang/test/OpenMP/simd_if_messages.cpp

Modified: 
    clang/include/clang/ASTMatchers/ASTMatchers.h
    clang/include/clang/Basic/OpenMPKinds.def
    clang/include/clang/Basic/OpenMPKinds.h
    clang/lib/Basic/OpenMPKinds.cpp
    clang/lib/CodeGen/CGOpenMPRuntime.h
    clang/lib/CodeGen/CGStmtOpenMP.cpp
    clang/lib/CodeGen/CodeGenFunction.h
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/test/OpenMP/simd_ast_print.cpp
    clang/test/OpenMP/simd_codegen.cpp

Removed: 
    


################################################################################
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 @@ class CGOpenMPRuntime {
                                                 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 @@ class CGOpenMPRuntime {
   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<OMPIfClause>()) {
+      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 @@ class CodeGenFunction : public CodeGenTypeCache {
     }
   };
 
+  /// 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 <class T, class S> // 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);
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to