diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp --- 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 @@ 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 @@ 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 @@ AO = llvm::AtomicOrdering::Monotonic; MemOrderingSpecified = true; } + llvm::SmallSet 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 @@ 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 --- 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 @@ SourceLocation AtomicKindLoc; OpenMPClauseKind MemOrderKind = OMPC_unknown; SourceLocation MemOrderLoc; + bool MutexClauseEncountered = false; + llvm::SmallSet 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 @@ } 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 @@ 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 @@ 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 --- a/clang/test/OpenMP/atomic_ast_print.cpp +++ b/clang/test/OpenMP/atomic_ast_print.cpp @@ -20,6 +20,7 @@ template T foo(T argc) { + T v = T(); T c = T(); T b = T(); T a = T(); @@ -45,6 +46,12 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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 @@ // 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@+1 {{in instantiation of function template specialization 'foo' requested here}} return foo(a); } diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp --- a/clang/test/OpenMP/atomic_messages.cpp +++ b/clang/test/OpenMP/atomic_messages.cpp @@ -954,6 +954,10 @@ // expected-note@+1 {{'read' clause used here}} #pragma omp atomic read compare a = b; +// expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'compare' clause}} +// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}} +#pragma omp atomic compare compare capture capture + a = b; #endif // expected-note@+1 {{in instantiation of function template specialization 'mixed' requested here}} return mixed();