Added full support for 'release' clause in flush|atomic directives.
}
};
+/// 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
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReleaseClause(OMPReleaseClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
return true;
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<
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)
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)
// 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
/// 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);
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_threads:
case OMPC_simd:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_device:
case OMPC_threads:
OS << "acquire";
}
+void OMPClausePrinter::VisitOMPReleaseClause(OMPReleaseClause *) {
+ OS << "release";
+}
+
void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
OS << "threads";
}
void OMPClauseProfiler::VisitOMPAcquireClause(const OMPAcquireClause *) {}
+void OMPClauseProfiler::VisitOMPReleaseClause(const OMPReleaseClause *) {}
+
void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {}
void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {}
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_device:
case OMPC_threads:
case OMPC_simd:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_device:
case OMPC_threads:
case OMPC_simd:
}
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) \
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_shared:
case OMPC_linear:
case OMPC_aligned:
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;
}
/// 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) {
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_threads:
case OMPC_simd:
case OMPC_nogroup:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_threads:
case OMPC_simd:
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
}
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
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_threads:
case OMPC_simd:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_threads:
case OMPC_simd:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_device:
case OMPC_threads:
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_depend:
case OMPC_device:
case OMPC_threads:
case OMPC_acquire:
Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
break;
+ case OMPC_release:
+ Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
+ break;
case OMPC_threads:
Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
break;
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);
case OMPC_seq_cst:
case OMPC_acq_rel:
case OMPC_acquire:
+ case OMPC_release:
case OMPC_device:
case OMPC_threads:
case OMPC_simd:
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) {
case OMPC_acquire:
C = new (Context) OMPAcquireClause();
break;
+ case OMPC_release:
+ C = new (Context) OMPReleaseClause();
+ break;
case OMPC_threads:
C = new (Context) OMPThreadsClause();
break;
void OMPClauseReader::VisitOMPAcquireClause(OMPAcquireClause *) {}
+void OMPClauseReader::VisitOMPReleaseClause(OMPReleaseClause *) {}
+
void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {}
void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
+void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
+
void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}
void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}
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();
}
// 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++;
// 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;
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
// 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);
}
// 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
// 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;
// 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;
// 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;
// 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;
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();
// 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:%.+]]
// 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),
#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
#pragma omp flush
#pragma omp flush acq_rel
#pragma omp flush acquire
+#pragma omp flush release
#pragma omp flush(a)
return a + 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) {
#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;
}
#pragma omp flush
#pragma omp flush acq_rel
#pragma omp flush acquire
+#pragma omp flush release
#pragma omp flush(a)
return a + argc;
}
#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
// 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,
#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);
#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"
void OMPClauseEnqueue::VisitOMPAcquireClause(const OMPAcquireClause *) {}
+void OMPClauseEnqueue::VisitOMPReleaseClause(const OMPReleaseClause *) {}
+
void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {}
void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}