[OPENMP50]Add support for 'release' clause.
authorAlexey Bataev <a.bataev@hotmail.com>
Mon, 10 Feb 2020 20:49:05 +0000 (15:49 -0500)
committerAlexey Bataev <a.bataev@hotmail.com>
Mon, 10 Feb 2020 21:01:41 +0000 (16:01 -0500)
Added full support for 'release' clause in flush|atomic directives.

24 files changed:
clang/include/clang/AST/OpenMPClause.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/OpenMPKinds.def
clang/include/clang/Sema/Sema.h
clang/lib/AST/OpenMPClause.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/Basic/OpenMPKinds.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/OpenMP/atomic_ast_print.cpp
clang/test/OpenMP/atomic_capture_codegen.cpp
clang/test/OpenMP/atomic_messages.cpp
clang/test/OpenMP/atomic_read_codegen.c
clang/test/OpenMP/atomic_update_codegen.cpp
clang/test/OpenMP/atomic_write_codegen.c
clang/test/OpenMP/flush_ast_print.cpp
clang/test/OpenMP/flush_codegen.cpp
clang/test/OpenMP/flush_messages.cpp
clang/tools/libclang/CIndex.cpp

index b9c4389ddd633fdc7d3b087c2d11cdda9bee1c48..19a84bd00a36dec33411913cd064d8471f5e6fcb 100644 (file)
@@ -1955,6 +1955,46 @@ public:
   }
 };
 
+/// This represents 'release' clause in the '#pragma omp atomic|flush'
+/// directives.
+///
+/// \code
+/// #pragma omp flush release
+/// \endcode
+/// In this example directive '#pragma omp flush' has 'release' clause.
+class OMPReleaseClause final : public OMPClause {
+public:
+  /// Build 'release' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  OMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_release, StartLoc, EndLoc) {}
+
+  /// Build an empty clause.
+  OMPReleaseClause()
+      : OMPClause(OMPC_release, SourceLocation(), SourceLocation()) {}
+
+  child_range children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+
+  const_child_range children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+
+  child_range used_children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+  const_child_range used_children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_release;
+  }
+};
+
 /// This represents clause 'private' in the '#pragma omp ...' directives.
 ///
 /// \code
index 916fac717dd4466d0aef939cc1dc8d085c5ca69f..4ef9528dcf5bb8c076bb421bb3a9c8c183495705 100644 (file)
@@ -3131,6 +3131,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
   return true;
 }
 
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReleaseClause(OMPReleaseClause *) {
+  return true;
+}
+
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
   return true;
index cc983f7507110ad43a38976fa1daabe5ca359b46..450075f2e9273a9e901229bdf432bd45fb6eac40 100644 (file)
@@ -9696,7 +9696,7 @@ def note_omp_atomic_capture: Note<
 def err_omp_atomic_several_clauses : Error<
   "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">;
 def err_omp_several_mem_order_clauses : Error<
-  "directive '#pragma omp %0' cannot contain more than one %select{'seq_cst', |}1'acq_rel' or 'acquire' clause">;
+  "directive '#pragma omp %0' cannot contain more than one %select{'seq_cst', |}1'acq_rel', 'acquire' or 'release' clause">;
 def note_omp_previous_mem_order_clause : Note<
   "'%0' clause used here">;
 def err_omp_target_contains_not_only_teams : Error<
index 346c0f54971df67a039515eb5bbb4381bf685a28..19fcf7cfac58cd9244aa60610b2c5f8210194da4 100644 (file)
@@ -259,6 +259,7 @@ OPENMP_CLAUSE(capture, OMPCaptureClause)
 OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
 OPENMP_CLAUSE(acq_rel, OMPAcqRelClause)
 OPENMP_CLAUSE(acquire, OMPAcquireClause)
+OPENMP_CLAUSE(release, OMPReleaseClause)
 OPENMP_CLAUSE(depend, OMPDependClause)
 OPENMP_CLAUSE(device, OMPDeviceClause)
 OPENMP_CLAUSE(threads, OMPThreadsClause)
@@ -493,6 +494,7 @@ OPENMP_ATOMIC_CLAUSE(capture)
 OPENMP_ATOMIC_CLAUSE(seq_cst)
 OPENMP_ATOMIC_CLAUSE(acq_rel)
 OPENMP_ATOMIC_CLAUSE(acquire)
+OPENMP_ATOMIC_CLAUSE(release)
 
 // Clauses allowed for OpenMP directive 'target'.
 OPENMP_TARGET_CLAUSE(if)
@@ -1092,6 +1094,7 @@ OPENMP_ORDER_KIND(concurrent)
 // Clauses allowed for OpenMP directive 'flush'.
 OPENMP_FLUSH_CLAUSE(acq_rel)
 OPENMP_FLUSH_CLAUSE(acquire)
+OPENMP_FLUSH_CLAUSE(release)
 
 #undef OPENMP_FLUSH_CLAUSE
 #undef OPENMP_ORDER_KIND
index beaeccd89820cd44d38a6e576e0984d74c477233..24cfceda45dcbfd88bd70064b42ba5fce03b2f62 100644 (file)
@@ -10334,6 +10334,9 @@ public:
   /// Called on well-formed 'acquire' clause.
   OMPClause *ActOnOpenMPAcquireClause(SourceLocation StartLoc,
                                       SourceLocation EndLoc);
+  /// Called on well-formed 'release' clause.
+  OMPClause *ActOnOpenMPReleaseClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
   /// Called on well-formed 'threads' clause.
   OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
                                       SourceLocation EndLoc);
index b9156e89173bfd65725a950730cd437f0d9dd61b..2947665981aff6f39f8b61ea417b88f07bf502b5 100644 (file)
@@ -118,6 +118,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_depend:
   case OMPC_threads:
   case OMPC_simd:
@@ -194,6 +195,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_depend:
   case OMPC_device:
   case OMPC_threads:
@@ -1346,6 +1348,10 @@ void OMPClausePrinter::VisitOMPAcquireClause(OMPAcquireClause *) {
   OS << "acquire";
 }
 
+void OMPClausePrinter::VisitOMPReleaseClause(OMPReleaseClause *) {
+  OS << "release";
+}
+
 void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
   OS << "threads";
 }
index abe988b80e7b9ce3bff593eacfb593540dc6b347..b303851a75c6f588c7a768df465748886778fe9c 100644 (file)
@@ -522,6 +522,8 @@ void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
 
 void OMPClauseProfiler::VisitOMPAcquireClause(const OMPAcquireClause *) {}
 
+void OMPClauseProfiler::VisitOMPReleaseClause(const OMPReleaseClause *) {}
+
 void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {}
 
 void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {}
index 18d97cda71e3afa75be3e38b3fd4a2dcf39f560c..124723552af4c9564c520959c6de162cbdfa58d3 100644 (file)
@@ -216,6 +216,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_device:
   case OMPC_threads:
   case OMPC_simd:
@@ -430,6 +431,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_device:
   case OMPC_threads:
   case OMPC_simd:
@@ -595,7 +597,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
     }
     break;
   case OMPD_atomic:
-    if (OpenMPVersion < 50 && (CKind == OMPC_acq_rel || CKind == OMPC_acquire))
+    if (OpenMPVersion < 50 && (CKind == OMPC_acq_rel || CKind == OMPC_acquire ||
+                               CKind == OMPC_release))
       return false;
     switch (CKind) {
 #define OPENMP_ATOMIC_CLAUSE(Name)                                             \
index 433506ff5818173a0c4713145a3e6c9f983c6008..bc71c27fd95f7416ec5f5e72138399802c36978e 100644 (file)
@@ -4493,6 +4493,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_shared:
   case OMPC_linear:
   case OMPC_aligned:
@@ -4546,12 +4547,16 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
     AO = llvm::AtomicOrdering::AcquireRelease;
   else if (S.getSingleClause<OMPAcquireClause>())
     AO = llvm::AtomicOrdering::Acquire;
+  else if (S.getSingleClause<OMPReleaseClause>())
+    AO = llvm::AtomicOrdering::Release;
   OpenMPClauseKind Kind = OMPC_unknown;
   for (const OMPClause *C : S.clauses()) {
-    // Find first clause (skip seq_cst|acq_rel|aqcuire clause, if it is first).
+    // Find first clause (skip seq_cst|acq_rel|aqcuire|release clause, if it is
+    // first).
     if (C->getClauseKind() != OMPC_seq_cst &&
         C->getClauseKind() != OMPC_acq_rel &&
-        C->getClauseKind() != OMPC_acquire) {
+        C->getClauseKind() != OMPC_acquire &&
+        C->getClauseKind() != OMPC_release) {
       Kind = C->getClauseKind();
       break;
     }
index 0214a6afa9098c889e0cb446ffbf9cbb0975aee3..1a7916e5adb865ff7f60b17b787f3db9c3fcf6c7 100644 (file)
@@ -2090,7 +2090,7 @@ bool Parser::ParseOpenMPSimpleVarList(
 ///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
 ///       from-clause | is_device_ptr-clause | task_reduction-clause |
 ///       in_reduction-clause | allocator-clause | allocate-clause |
-///       acq_rel-clause | acquire-clause
+///       acq_rel-clause | acquire-clause | release-clause
 ///
 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
                                      OpenMPClauseKind CKind, bool FirstClause) {
@@ -2201,6 +2201,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_threads:
   case OMPC_simd:
   case OMPC_nogroup:
index ed2320c8ab426974a2d8a764e90f1fcf53a7c751..2e3c75fed37017cda6ec52c43e7f712cf6d56031 100644 (file)
@@ -4989,6 +4989,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
       case OMPC_seq_cst:
       case OMPC_acq_rel:
       case OMPC_acquire:
+      case OMPC_release:
       case OMPC_depend:
       case OMPC_threads:
       case OMPC_simd:
@@ -8575,9 +8576,9 @@ StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
   OpenMPClauseKind MemOrderKind = OMPC_unknown;
   SourceLocation MemOrderLoc;
   for (const OMPClause *C : Clauses) {
-    if (C->getClauseKind() == OMPC_seq_cst ||
-        C->getClauseKind() == OMPC_acq_rel ||
-        C->getClauseKind() == OMPC_acquire) {
+    if (C->getClauseKind() == OMPC_acq_rel ||
+        C->getClauseKind() == OMPC_acquire ||
+        C->getClauseKind() == OMPC_release) {
       if (MemOrderKind != OMPC_unknown) {
         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
             << getOpenMPDirectiveName(OMPD_flush) << 1
@@ -8953,7 +8954,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
     }
     if (C->getClauseKind() == OMPC_seq_cst ||
         C->getClauseKind() == OMPC_acq_rel ||
-        C->getClauseKind() == OMPC_acquire) {
+        C->getClauseKind() == OMPC_acquire ||
+        C->getClauseKind() == OMPC_release) {
       if (MemOrderKind != OMPC_unknown) {
         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
             << getOpenMPDirectiveName(OMPD_atomic) << 0
@@ -10893,6 +10895,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_depend:
   case OMPC_threads:
   case OMPC_simd:
@@ -11607,6 +11610,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_depend:
   case OMPC_threads:
   case OMPC_simd:
@@ -12031,6 +12035,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_depend:
   case OMPC_device:
   case OMPC_threads:
@@ -12233,6 +12238,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_depend:
   case OMPC_device:
   case OMPC_threads:
@@ -12412,6 +12418,9 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
   case OMPC_acquire:
     Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
     break;
+  case OMPC_release:
+    Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
+    break;
   case OMPC_threads:
     Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
     break;
@@ -12535,6 +12544,11 @@ OMPClause *Sema::ActOnOpenMPAcquireClause(SourceLocation StartLoc,
   return new (Context) OMPAcquireClause(StartLoc, EndLoc);
 }
 
+OMPClause *Sema::ActOnOpenMPReleaseClause(SourceLocation StartLoc,
+                                          SourceLocation EndLoc) {
+  return new (Context) OMPReleaseClause(StartLoc, EndLoc);
+}
+
 OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc,
                                           SourceLocation EndLoc) {
   return new (Context) OMPThreadsClause(StartLoc, EndLoc);
@@ -12693,6 +12707,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
   case OMPC_seq_cst:
   case OMPC_acq_rel:
   case OMPC_acquire:
+  case OMPC_release:
   case OMPC_device:
   case OMPC_threads:
   case OMPC_simd:
index 28ff3fdfc41c7dd4cc74731eaa1d7169ffb82086..dffaf893862798747e8054f1800c7bb8069151f6 100644 (file)
@@ -8818,6 +8818,13 @@ TreeTransform<Derived>::TransformOMPAcquireClause(OMPAcquireClause *C) {
   return C;
 }
 
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPReleaseClause(OMPReleaseClause *C) {
+  // No need to rebuild this clause, no template-dependent parameters.
+  return C;
+}
+
 template <typename Derived>
 OMPClause *
 TreeTransform<Derived>::TransformOMPThreadsClause(OMPThreadsClause *C) {
index 89b8e314e8f813206fe8d61a59b7031109584ef0..c9553de8143e33cd704f51380a418e9742b85f86 100644 (file)
@@ -11672,6 +11672,9 @@ OMPClause *OMPClauseReader::readClause() {
   case OMPC_acquire:
     C = new (Context) OMPAcquireClause();
     break;
+  case OMPC_release:
+    C = new (Context) OMPReleaseClause();
+    break;
   case OMPC_threads:
     C = new (Context) OMPThreadsClause();
     break;
@@ -11938,6 +11941,8 @@ void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
 
 void OMPClauseReader::VisitOMPAcquireClause(OMPAcquireClause *) {}
 
+void OMPClauseReader::VisitOMPReleaseClause(OMPReleaseClause *) {}
+
 void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {}
 
 void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
index 7263e65b479254108e56ea0455350e65892ed1f9..eb79ba20ddf7a5ab900662579101f7a3ea8d15c0 100644 (file)
@@ -6151,6 +6151,8 @@ void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
 
 void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
 
+void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
+
 void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}
 
 void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
index 1cc4289d42f4864b48b2b90183094c48baef727a..4dd64a75f2c906516f5bb933bfa33930024514ae 100644 (file)
@@ -74,6 +74,21 @@ T foo(T argc) {
     a = b;
     b++;
   }
+#pragma omp atomic release
+  a++;
+#pragma omp atomic read release
+  a = argc;
+#pragma omp atomic release write
+  a = argc + argc;
+#pragma omp atomic update release
+  a = a + argc;
+#pragma omp atomic release capture
+  a = b++;
+#pragma omp atomic capture release
+  {
+    a = b;
+    b++;
+  }
   return T();
 }
 
@@ -138,6 +153,21 @@ T foo(T argc) {
 // CHECK-NEXT: a = b;
 // CHECK-NEXT: b++;
 // CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp atomic release
+// CHECK-NEXT: a++;
+// CHECK-NEXT: #pragma omp atomic read release
+// CHECK-NEXT: a = argc;
+// CHECK-NEXT: #pragma omp atomic release write
+// CHECK-NEXT: a = argc + argc;
+// CHECK-NEXT: #pragma omp atomic update release
+// CHECK-NEXT: a = a + argc;
+// CHECK-NEXT: #pragma omp atomic release capture
+// CHECK-NEXT: a = b++;
+// CHECK-NEXT: #pragma omp atomic capture release
+// CHECK-NEXT: {
+// CHECK-NEXT: a = b;
+// CHECK-NEXT: b++;
+// CHECK-NEXT: }
 // CHECK: int a = int();
 // CHECK-NEXT: #pragma omp atomic
 // CHECK-NEXT: a++;
@@ -199,6 +229,21 @@ T foo(T argc) {
 // CHECK-NEXT: a = b;
 // CHECK-NEXT: b++;
 // CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp atomic release
+// CHECK-NEXT: a++;
+// CHECK-NEXT: #pragma omp atomic read release
+// CHECK-NEXT: a = argc;
+// CHECK-NEXT: #pragma omp atomic release write
+// CHECK-NEXT: a = argc + argc;
+// CHECK-NEXT: #pragma omp atomic update release
+// CHECK-NEXT: a = a + argc;
+// CHECK-NEXT: #pragma omp atomic release capture
+// CHECK-NEXT: a = b++;
+// CHECK-NEXT: #pragma omp atomic capture release
+// CHECK-NEXT: {
+// CHECK-NEXT: a = b;
+// CHECK-NEXT: b++;
+// CHECK-NEXT: }
 
 int main(int argc, char **argv) {
   int b = 0;
@@ -264,6 +309,21 @@ int main(int argc, char **argv) {
     a = b;
     b++;
   }
+#pragma omp atomic release
+  a++;
+#pragma omp atomic read release
+  a = argc;
+#pragma omp atomic release write
+  a = argc + argc;
+#pragma omp atomic update release
+  a = a + argc;
+#pragma omp atomic release capture
+  a = b++;
+#pragma omp atomic capture release
+  {
+    a = b;
+    b++;
+  }
   // CHECK-NEXT: #pragma omp atomic
   // CHECK-NEXT: a++;
   // CHECK-NEXT: #pragma omp atomic read
@@ -324,6 +384,21 @@ int main(int argc, char **argv) {
   // CHECK-NEXT: a = b;
   // CHECK-NEXT: b++;
   // CHECK-NEXT: }
+  // CHECK-NEXT: #pragma omp atomic release
+  // CHECK-NEXT: a++;
+  // CHECK-NEXT: #pragma omp atomic read release
+  // CHECK-NEXT: a = argc;
+  // CHECK-NEXT: #pragma omp atomic release write
+  // CHECK-NEXT: a = argc + argc;
+  // CHECK-NEXT: #pragma omp atomic update release
+  // CHECK-NEXT: a = a + argc;
+  // CHECK-NEXT: #pragma omp atomic release capture
+  // CHECK-NEXT: a = b++;
+  // CHECK-NEXT: #pragma omp atomic capture release
+  // CHECK-NEXT: {
+  // CHECK-NEXT: a = b;
+  // CHECK-NEXT: b++;
+  // CHECK-NEXT: }
   return foo(a);
 }
 
index d3d4e0800ec272012b62a299e1969603d8a7631f..3164c4f419f52dea04e4d296723f082c299fd899 100644 (file)
@@ -896,14 +896,15 @@ int main() {
 // CHECK: [[VAL:%.+]] = or i64 [[BF_CLEAR]], [[BF_VALUE]]
 // CHECK: store i64 [[VAL]], i64* [[TEMP1]]
 // CHECK: [[NEW_BF_VALUE:%.+]] = load i64, i64* [[TEMP1]]
-// CHECK: [[RES:%.+]] = cmpxchg i64* bitcast (%struct.BitFields4* @{{.+}} to i64*), i64 [[OLD_BF_VALUE]], i64 [[NEW_BF_VALUE]] monotonic monotonic
+// CHECK: [[RES:%.+]] = cmpxchg i64* bitcast (%struct.BitFields4* @{{.+}} to i64*), i64 [[OLD_BF_VALUE]], i64 [[NEW_BF_VALUE]] release monotonic
 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i64, i1 } [[RES]], 0
 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i64, i1 } [[RES]], 1
 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]]
 // CHECK: [[EXIT]]
 // CHECK: [[NEW_VAL:%.+]] = trunc i64 [[CONV]] to i32
 // CHECK: store i32 [[NEW_VAL]], i32* @{{.+}},
-#pragma omp atomic capture
+// CHECK: call{{.*}} @__kmpc_flush(
+#pragma omp atomic capture release
   {bfx4.b /= ldv; iv = bfx4.b;}
 // CHECK: [[EXPR:%.+]] = load x86_fp80, x86_fp80* @{{.+}}
 // CHECK: [[PREV_VALUE:%.+]] = load atomic i8, i8* getelementptr inbounds (%struct.BitFields4_packed, %struct.BitFields4_packed* @{{.+}}, i32 0, i32 0, i64 2) acquire
index 9489eb13fc10ef1b5df88b1dee657a4ca1e37673..d595689e4d15c1558927c46709852c85990761ec 100644 (file)
@@ -733,7 +733,7 @@ T acq_rel() {
   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
   // expected-note@+1 {{expected an expression statement}}
   ;
-// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel' or 'acquire' clause}} omp50-note@+1 2 {{'acq_rel' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
+// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'acq_rel' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
 #pragma omp atomic acq_rel seq_cst
   a += b;
 
@@ -754,7 +754,7 @@ int acq_rel() {
   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
   // expected-note@+1 {{expected an expression statement}}
   ;
-// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel' or 'acquire' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
+// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}}
 #pragma omp atomic seq_cst acq_rel
   a += b;
 
@@ -775,7 +775,7 @@ T acquire() {
   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
   // expected-note@+1 {{expected an expression statement}}
   ;
-// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel' or 'acquire' clause}} omp50-note@+1 2 {{'acquire' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
+// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'acquire' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
 #pragma omp atomic acquire seq_cst
   a += b;
 
@@ -796,7 +796,7 @@ int acquire() {
   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
   // expected-note@+1 {{expected an expression statement}}
   ;
-// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel' or 'acquire' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
+// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acquire' in directive '#pragma omp atomic'}}
 #pragma omp atomic seq_cst acquire
   a += b;
 
@@ -809,6 +809,48 @@ int acquire() {
  return acquire<int>(); // omp50-note {{in instantiation of function template specialization 'acquire<int>' requested here}}
 }
 
+template <class T>
+T release() {
+  T a = 0, b = 0;
+// omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+#pragma omp atomic release
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
+  ;
+// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 2 {{'release' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+#pragma omp atomic release seq_cst
+  a += b;
+
+// omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+#pragma omp atomic update release
+  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
+  ;
+
+  return T();
+}
+
+int release() {
+  int a = 0, b = 0;
+// Test for atomic release
+// omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+#pragma omp atomic release
+  // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
+  ;
+// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst', 'acq_rel', 'acquire' or 'release' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+#pragma omp atomic seq_cst release
+  a += b;
+
+// omp45-error@+1 {{unexpected OpenMP clause 'release' in directive '#pragma omp atomic'}}
+#pragma omp atomic update release
+  // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note@+1 {{expected an expression statement}}
+  ;
+
+ return release<int>(); // omp50-note {{in instantiation of function template specialization 'release<int>' requested here}}
+}
+
 template <class T>
 T mixed() {
   T a, b = T();
index 713f370a1012412e7d2fc62c52da315ea4af068e..814975e38ea27a4935306b41fd4d739953d61491 100644 (file)
@@ -312,7 +312,7 @@ int main() {
 // CHECK: [[SHL:%.+]] = shl i64 [[LD]], 40
 // CHECK: [[ASHR:%.+]] = ashr i64 [[SHL]], 57
 // CHECK: store x86_fp80
-#pragma omp atomic read
+#pragma omp atomic read release
   ldv = bfx4.b;
 // CHECK: [[LD:%.+]] = load atomic i8, i8* getelementptr inbounds (%struct.BitFields4_packed, %struct.BitFields4_packed* @bfx4_packed, i32 0, i32 0, i64 2) acquire
 // CHECK: store i8 [[LD]], i8* [[LDTEMP:%.+]]
index 31995f7ae8e9094e6cd0d226d1111bfdad61560e..fb900753898c533d9344cce1ccbeacbcd11a3c11 100644 (file)
@@ -529,12 +529,13 @@ int main() {
 // CHECK: [[DESIRED:%.+]] = zext i1 [[BOOL_DESIRED]] to i8
 // CHECK: store i8 [[DESIRED]], i8* [[TEMP:%.+]]
 // CHECK: [[DESIRED:%.+]] = load i8, i8* [[TEMP]]
-// CHECK: [[RES:%.+]] = cmpxchg i8* [[X_ADDR]], i8 [[EXPECTED]], i8 [[DESIRED]] monotonic monotonic
+// CHECK: [[RES:%.+]] = cmpxchg i8* [[X_ADDR]], i8 [[EXPECTED]], i8 [[DESIRED]] release monotonic
 // CHECK: [[OLD_XI8:%.+]] = extractvalue { i8, i1 } [[RES]], 0
 // CHECK: [[SUCCESS_FAIL:%.+]] = extractvalue { i8, i1 } [[RES]], 1
 // CHECK: br i1 [[SUCCESS_FAIL]], label %[[EXIT:.+]], label %[[CONT]]
 // CHECK: [[EXIT]]
-#pragma omp atomic update
+// CHECK: call{{.*}} @__kmpc_flush(
+#pragma omp atomic update release
   bx = ldv * bx;
 // CHECK: [[EXPR_RE:%.+]] = load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* [[CIV_ADDR:@.+]], i32 0, i32 0),
 // CHECK: [[EXPR_IM:%.+]] = load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* [[CIV_ADDR]], i32 0, i32 1),
index c8e8d343252a45de86310001afbb2ff16111e529..f8a74e8c6edd27f095e7083938c3318a018c07a1 100644 (file)
@@ -91,8 +91,8 @@ int main() {
 #pragma omp atomic write acquire
   bx = bv;
 // CHECK: load i8, i8*
-// CHECK: store atomic i8
-#pragma omp atomic write
+// CHECK: store atomic i8{{.*}}release
+#pragma omp atomic write release
   cx = cv;
 // CHECK: load i8, i8*
 // CHECK: store atomic i8
index bfbe8c3c3268beb3902e34be704700d9001e6c79..2f2dbba75c9efcc8ea3d4a8f17d40ca55a3bd03a 100644 (file)
@@ -18,6 +18,7 @@ T tmain(T argc) {
 #pragma omp flush
 #pragma omp flush acq_rel
 #pragma omp flush acquire
+#pragma omp flush release
 #pragma omp flush(a)
   return a + argc;
 }
@@ -25,16 +26,19 @@ T tmain(T argc) {
 // CHECK-NEXT: #pragma omp flush{{$}}
 // CHECK-NEXT: #pragma omp flush acq_rel{{$}}
 // CHECK-NEXT: #pragma omp flush acquire{{$}}
+// CHECK-NEXT: #pragma omp flush release{{$}}
 // CHECK-NEXT: #pragma omp flush (a)
 // CHECK:      static int a;
 // CHECK-NEXT: #pragma omp flush
 // CHECK-NEXT: #pragma omp flush acq_rel{{$}}
 // CHECK-NEXT: #pragma omp flush acquire{{$}}
+// CHECK-NEXT: #pragma omp flush release{{$}}
 // CHECK-NEXT: #pragma omp flush (a)
 // CHECK:      static char a;
 // CHECK-NEXT: #pragma omp flush
 // CHECK-NEXT: #pragma omp flush acq_rel{{$}}
 // CHECK-NEXT: #pragma omp flush acquire{{$}}
+// CHECK-NEXT: #pragma omp flush release{{$}}
 // CHECK-NEXT: #pragma omp flush (a)
 
 int main(int argc, char **argv) {
@@ -43,10 +47,12 @@ int main(int argc, char **argv) {
 #pragma omp flush
 #pragma omp flush acq_rel
 #pragma omp flush acquire
+#pragma omp flush release
 #pragma omp flush(a)
 // CHECK-NEXT: #pragma omp flush
 // CHECK-NEXT: #pragma omp flush acq_rel
 // CHECK-NEXT: #pragma omp flush acquire{{$}}
+// CHECK-NEXT: #pragma omp flush release
 // CHECK-NEXT: #pragma omp flush (a)
   return tmain(argc) + tmain(argv[0][0]) + a;
 }
index ce66d98ead2031c66e46bbdbebbee59d02693636..36ab677a7e8205de03b28fdfba41ee10fa5f9397 100644 (file)
@@ -19,6 +19,7 @@ T tmain(T argc) {
 #pragma omp flush
 #pragma omp flush acq_rel
 #pragma omp flush acquire
+#pragma omp flush release
 #pragma omp flush(a)
   return a + argc;
 }
@@ -29,11 +30,13 @@ int main() {
 #pragma omp flush
 #pragma omp flush acq_rel
 #pragma omp flush acquire
+#pragma omp flush release
 #pragma omp flush(a)
   // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
   // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
   // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
   // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
+  // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
   return tmain(a);
   // CHECK: call {{.*}} [[TMAIN:@.+]](
   // CHECK: ret
@@ -44,6 +47,7 @@ int main() {
 // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
 // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
 // CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
+// CHECK: call {{.*}}void @__kmpc_flush(%{{.+}}* {{(@|%).+}})
 // CHECK: ret
 
 // CHECK-NOT: line: 0,
index 9ed08e2ba38e777fcc850282eeb4e2dd14f07f6b..48a70f3f8dcb5364fbfea5d34901cf028cbe2718 100644 (file)
@@ -137,7 +137,9 @@ label1 : {
 #pragma omp flush seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp flush'}}
 #pragma omp flush acq_rel // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}}
 #pragma omp flush acquire // omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}}
-#pragma omp flush acq_rel acquire // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel' or 'acquire' clause}} omp50-note {{'acq_rel' clause used here}}
+#pragma omp flush release // omp45-error {{unexpected OpenMP clause 'release' in directive '#pragma omp flush'}}
+#pragma omp flush acq_rel acquire // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel', 'acquire' or 'release' clause}} omp50-note {{'acq_rel' clause used here}}
+#pragma omp flush release acquire // omp45-error {{unexpected OpenMP clause 'release' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel', 'acquire' or 'release' clause}} omp50-note {{'release' clause used here}}
 #pragma omp flush acq_rel (argc) // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}}
 #pragma omp flush(argc) acq_rel // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}}
   return tmain(argc);
index 5dc33bd445486f7388067029331f8e62e5b48402..12479c7abb84e7bab1bb7e5195ee3339f3f77e87 100644 (file)
@@ -23,6 +23,7 @@
 #include "clang-c/FatalErrorHandler.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Mangle.h"
+#include "clang/AST/OpenMPClause.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticCategories.h"
@@ -2238,6 +2239,8 @@ void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
 
 void OMPClauseEnqueue::VisitOMPAcquireClause(const OMPAcquireClause *) {}
 
+void OMPClauseEnqueue::VisitOMPReleaseClause(const OMPReleaseClause *) {}
+
 void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {}
 
 void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}