[clang] ccebf8a - [Clang][OpenMP] Add support for compare capture in parser
Shilei Tian via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 18 07:24:06 PST 2022
Author: Shilei Tian
Date: 2022-02-18T10:23:59-05:00
New Revision: ccebf8ac8c61cbd46223abbeb4f29f4e1f7b490c
URL: https://github.com/llvm/llvm-project/commit/ccebf8ac8c61cbd46223abbeb4f29f4e1f7b490c
DIFF: https://github.com/llvm/llvm-project/commit/ccebf8ac8c61cbd46223abbeb4f29f4e1f7b490c.diff
LOG: [Clang][OpenMP] Add support for compare capture in parser
This patch adds the support for `atomic compare capture` in parser and part of
sema. We don't create an AST node for this because the spec doesn't say `compare`
and `capture` clauses should be used tightly, so we cannot look one more token
ahead in the parser.
Reviewed By: ABataev
Differential Revision: https://reviews.llvm.org/D116261
Added:
Modified:
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/test/OpenMP/atomic_ast_print.cpp
clang/test/OpenMP/atomic_messages.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index b491642871ce..8ea4968f4b11 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
@@ -6020,7 +6021,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
llvm::AtomicOrdering AO, bool IsPostfixUpdate,
const Expr *X, const Expr *V, const Expr *E,
const Expr *UE, bool IsXLHSInRHSPart,
- SourceLocation Loc) {
+ bool IsCompareCapture, SourceLocation Loc) {
switch (Kind) {
case OMPC_read:
emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
@@ -6037,10 +6038,19 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
IsXLHSInRHSPart, Loc);
break;
case OMPC_compare: {
- // Emit an error here.
- unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID(
- DiagnosticsEngine::Error, "'atomic compare' is not supported for now");
- CGF.CGM.getDiags().Report(DiagID);
+ if (IsCompareCapture) {
+ // Emit an error here.
+ unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "'atomic compare capture' is not supported for now");
+ CGF.CGM.getDiags().Report(DiagID);
+ } else {
+ // Emit an error here.
+ unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "'atomic compare' is not supported for now");
+ CGF.CGM.getDiags().Report(DiagID);
+ }
break;
}
case OMPC_if:
@@ -6153,18 +6163,23 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
AO = llvm::AtomicOrdering::Monotonic;
MemOrderingSpecified = true;
}
+ llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
OpenMPClauseKind Kind = OMPC_unknown;
for (const OMPClause *C : S.clauses()) {
// Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
// if it is first).
- if (C->getClauseKind() != OMPC_seq_cst &&
- C->getClauseKind() != OMPC_acq_rel &&
- C->getClauseKind() != OMPC_acquire &&
- C->getClauseKind() != OMPC_release &&
- C->getClauseKind() != OMPC_relaxed && C->getClauseKind() != OMPC_hint) {
- Kind = C->getClauseKind();
- break;
- }
+ OpenMPClauseKind K = C->getClauseKind();
+ if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
+ K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
+ continue;
+ Kind = K;
+ KindsEncountered.insert(K);
+ }
+ bool IsCompareCapture = false;
+ if (KindsEncountered.contains(OMPC_compare) &&
+ KindsEncountered.contains(OMPC_capture)) {
+ IsCompareCapture = true;
+ Kind = OMPC_compare;
}
if (!MemOrderingSpecified) {
llvm::AtomicOrdering DefaultOrder =
@@ -6188,7 +6203,7 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
EmitStopPoint(S.getAssociatedStmt());
emitOMPAtomicExpr(*this, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(),
S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(),
- S.getBeginLoc());
+ IsCompareCapture, S.getBeginLoc());
}
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 64647f59fcb5..686cef249f3a 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -35,6 +35,7 @@
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Frontend/OpenMP/OMPAssume.h"
#include "llvm/Frontend/OpenMP/OMPConstants.h"
@@ -11322,14 +11323,18 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation AtomicKindLoc;
OpenMPClauseKind MemOrderKind = OMPC_unknown;
SourceLocation MemOrderLoc;
+ bool MutexClauseEncountered = false;
+ llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
for (const OMPClause *C : Clauses) {
switch (C->getClauseKind()) {
case OMPC_read:
case OMPC_write:
case OMPC_update:
+ MutexClauseEncountered = true;
+ LLVM_FALLTHROUGH;
case OMPC_capture:
case OMPC_compare: {
- if (AtomicKind != OMPC_unknown) {
+ if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
<< SourceRange(C->getBeginLoc(), C->getEndLoc());
Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
@@ -11337,6 +11342,12 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
} else {
AtomicKind = C->getClauseKind();
AtomicKindLoc = C->getBeginLoc();
+ if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
+ Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
+ << SourceRange(C->getBeginLoc(), C->getEndLoc());
+ Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
+ << getOpenMPClauseName(AtomicKind);
+ }
}
break;
}
@@ -11364,6 +11375,12 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
llvm_unreachable("unknown clause is encountered");
}
}
+ bool IsCompareCapture = false;
+ if (EncounteredAtomicKinds.contains(OMPC_compare) &&
+ EncounteredAtomicKinds.contains(OMPC_capture)) {
+ IsCompareCapture = true;
+ AtomicKind = OMPC_compare;
+ }
// OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
// If atomic-clause is read then memory-order-clause must not be acq_rel or
// release.
@@ -11782,17 +11799,22 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if (CurContext->isDependentContext())
UE = V = E = X = nullptr;
} else if (AtomicKind == OMPC_compare) {
- OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
- OpenMPAtomicCompareChecker Checker(*this);
- if (!Checker.checkStmt(Body, ErrorInfo)) {
- Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
- << ErrorInfo.ErrorRange;
- Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
- << ErrorInfo.Error << ErrorInfo.NoteRange;
- return StmtError();
+ if (IsCompareCapture) {
+ // TODO: We don't set X, D, E, etc. here because in code gen we will emit
+ // error directly.
+ } else {
+ OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
+ OpenMPAtomicCompareChecker Checker(*this);
+ if (!Checker.checkStmt(Body, ErrorInfo)) {
+ Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
+ << ErrorInfo.ErrorRange;
+ Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
+ << ErrorInfo.Error << ErrorInfo.NoteRange;
+ return StmtError();
+ }
+ // TODO: We don't set X, D, E, etc. here because in code gen we will emit
+ // error directly.
}
- // TODO: We don't set X, D, E, etc. here because in code gen we will emit
- // error directly.
}
setFunctionHasBranchProtectedScope();
diff --git a/clang/test/OpenMP/atomic_ast_print.cpp b/clang/test/OpenMP/atomic_ast_print.cpp
index 9484917dde83..7502fdc339c2 100644
--- a/clang/test/OpenMP/atomic_ast_print.cpp
+++ b/clang/test/OpenMP/atomic_ast_print.cpp
@@ -20,6 +20,7 @@
template <class T>
T foo(T argc) {
+ T v = T();
T c = T();
T b = T();
T a = T();
@@ -45,6 +46,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic seq_cst
a++;
@@ -68,6 +75,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare seq_cst
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture seq_cst
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare seq_cst capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture seq_cst
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic
a++;
@@ -91,6 +104,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare acq_rel
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture acq_rel
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare acq_rel capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture acq_rel
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic
a++;
@@ -114,6 +133,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare acquire
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture acquire
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare acquire capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture acquire
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic release
a++;
@@ -137,6 +162,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare release
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture release
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare release capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture release
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic relaxed
a++;
@@ -160,6 +191,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare relaxed
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture relaxed
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare relaxed capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture relaxed
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic hint(6)
a++;
@@ -183,6 +220,12 @@ T foo(T argc) {
{ a = a < b ? b : a; }
#pragma omp atomic compare hint(6)
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture hint(6)
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare hint(6) capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture hint(6)
+ { v = a == b; if (v) a = c; }
#endif
return T();
}
@@ -215,6 +258,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic seq_cst
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read seq_cst
@@ -242,6 +301,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture seq_cst
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare seq_cst capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture seq_cst
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -269,6 +344,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acq_rel
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare acq_rel capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acq_rel
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acquire
@@ -296,6 +387,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acquire
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare acquire capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acquire
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic release
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -323,6 +430,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture release
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare release capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture release
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic relaxed
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -350,6 +473,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture relaxed
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare relaxed capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture relaxed
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic hint(6)
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read hint(6)
@@ -377,6 +516,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture hint(6)
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare hint(6) capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture hint(6)
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK: int a = int();
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
@@ -405,6 +560,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic seq_cst
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read seq_cst
@@ -432,6 +603,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture seq_cst
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare seq_cst capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture seq_cst
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -459,6 +646,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acq_rel
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare acq_rel capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acq_rel
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acquire
@@ -486,6 +689,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acquire
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare acquire capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture acquire
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic release
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -513,6 +732,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture release
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare release capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture release
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic relaxed
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -540,6 +775,22 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture relaxed
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare relaxed capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture relaxed
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic hint(6)
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read hint(6)
@@ -567,8 +818,25 @@ T foo(T argc) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture hint(6)
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a > b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare hint(6) capture
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a;
+// CHECK-51-NEXT: a = a < b ? b : a;
+// CHECK-51-NEXT: }
+// CHECK-51-NEXT: #pragma omp atomic compare capture hint(6)
+// CHECK-51-NEXT: {
+// CHECK-51-NEXT: v = a == b;
+// CHECK-51-NEXT: if (v)
+// CHECK-51-NEXT: a = c;
+// CHECK-51-NEXT: }
int main(int argc, char **argv) {
+ int v = 0;
int c = 0;
int b = 0;
int a = 0;
@@ -595,6 +863,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic seq_cst
a++;
@@ -618,6 +892,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare seq_cst
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture seq_cst
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare seq_cst capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture seq_cst
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic
a++;
@@ -641,6 +921,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare acq_rel
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture acq_rel
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare acq_rel capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture acq_rel
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic
a++;
@@ -664,6 +950,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare acquire
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture acquire
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare acquire capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture acquire
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic release
a++;
@@ -687,6 +979,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare release
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture release
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare release capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture release
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic relaxed
a++;
@@ -710,6 +1008,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare relaxed
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture relaxed
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare relaxed capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture relaxed
+ { v = a == b; if (v) a = c; }
#endif
#pragma omp atomic hint(6)
a++;
@@ -733,6 +1037,12 @@ int main(int argc, char **argv) {
{ a = a < b ? b : a; }
#pragma omp atomic compare hint(6)
{ a = a == b ? c : a; }
+#pragma omp atomic compare capture hint(6)
+ { v = a; a = a > b ? b : a; }
+#pragma omp atomic compare hint(6) capture
+ { v = a; a = a < b ? b : a; }
+#pragma omp atomic compare capture hint(6)
+ { v = a == b; if (v) a = c; }
#endif
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
@@ -761,6 +1071,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic seq_cst
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read seq_cst
@@ -788,6 +1114,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture seq_cst
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare seq_cst capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture seq_cst
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -815,6 +1157,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture acq_rel
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare acq_rel capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture acq_rel
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read acquire
@@ -842,6 +1200,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture acquire
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare acquire capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture acquire
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic release
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -869,6 +1243,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture release
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare release capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture release
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic relaxed
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -896,6 +1286,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture relaxed
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare relaxed capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture relaxed
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// CHECK-NEXT: #pragma omp atomic hint(6)
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read hint(6)
@@ -923,6 +1329,22 @@ int main(int argc, char **argv) {
// CHECK-51-NEXT: {
// CHECK-51-NEXT: a = a == b ? c : a;
// CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture hint(6)
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a > b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare hint(6) capture
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a;
+ // CHECK-51-NEXT: a = a < b ? b : a;
+ // CHECK-51-NEXT: }
+ // CHECK-51-NEXT: #pragma omp atomic compare capture hint(6)
+ // CHECK-51-NEXT: {
+ // CHECK-51-NEXT: v = a == b;
+ // CHECK-51-NEXT: if (v)
+ // CHECK-51-NEXT: a = c;
+ // CHECK-51-NEXT: }
// expect-note at +1 {{in instantiation of function template specialization 'foo<int>' requested here}}
return foo(a);
}
diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp
index 3e4ffa841ecd..700c86da1a58 100644
--- a/clang/test/OpenMP/atomic_messages.cpp
+++ b/clang/test/OpenMP/atomic_messages.cpp
@@ -954,6 +954,10 @@ int mixed() {
// expected-note at +1 {{'read' clause used here}}
#pragma omp atomic read compare
a = b;
+// expected-error at +2 {{directive '#pragma omp atomic' cannot contain more than one 'compare' clause}}
+// expected-error at +1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
+#pragma omp atomic compare compare capture capture
+ a = b;
#endif
// expected-note at +1 {{in instantiation of function template specialization 'mixed<int>' requested here}}
return mixed<int>();
More information about the cfe-commits
mailing list