forked from OSchip/llvm-project
[OPENMP50]Full handling of atomic_default_mem_order in requires
directive. According to OpenMP 5.0, The atomic_default_mem_order clause specifies the default memory ordering behavior for atomic constructs that must be provided by an implementation. If the default memory ordering is specified as seq_cst, all atomic constructs on which memory-order-clause is not specified behave as if the seq_cst clause appears. If the default memory ordering is specified as relaxed, all atomic constructs on which memory-order-clause is not specified behave as if the relaxed clause appears. If the default memory ordering is specified as acq_rel, atomic constructs on which memory-order-clause is not specified behave as if the release clause appears if the atomic write or atomic update operation is specified, as if the acquire clause appears if the atomic read operation is specified, and as if the acq_rel clause appears if the atomic captured update operation is specified.
This commit is contained in:
parent
257e412762
commit
2d4f80f78a
|
@ -9852,10 +9852,10 @@ def err_omp_requires_clause_redeclaration : Error <
|
|||
"Only one %0 clause can appear on a requires directive in a single translation unit">;
|
||||
def note_omp_requires_previous_clause : Note <
|
||||
"%0 clause previously used here">;
|
||||
def err_omp_target_before_requires : Error <
|
||||
"target region encountered before requires directive with '%0' clause">;
|
||||
def note_omp_requires_encountered_target : Note <
|
||||
"target previously encountered here">;
|
||||
def err_omp_directive_before_requires : Error <
|
||||
"'%0' region encountered before requires directive with '%1' clause">;
|
||||
def note_omp_requires_encountered_directive : Note <
|
||||
"'%0' previously encountered here">;
|
||||
def err_omp_invalid_scope : Error <
|
||||
"'#pragma omp %0' directive must appear only in file scope">;
|
||||
def note_omp_invalid_length_on_this_ptr_mapping : Note <
|
||||
|
|
|
@ -10041,6 +10041,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
|||
return true;
|
||||
else if (isa<PragmaDetectMismatchDecl>(D))
|
||||
return true;
|
||||
else if (isa<OMPRequiresDecl>(D))
|
||||
return true;
|
||||
else if (isa<OMPThreadPrivateDecl>(D))
|
||||
return !D->getDeclContext()->isDependentContext();
|
||||
else if (isa<OMPAllocateDecl>(D))
|
||||
|
|
|
@ -2537,5 +2537,5 @@ void CodeGenModule::EmitOMPDeclareMapper(const OMPDeclareMapperDecl *D,
|
|||
}
|
||||
|
||||
void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) {
|
||||
getOpenMPRuntime().checkArchForUnifiedAddressing(D);
|
||||
getOpenMPRuntime().processRequiresDirective(D);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Basic/BitmaskEnum.h"
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/CodeGen/ConstantInitBuilder.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SetOperations.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Support/AtomicOrdering.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
|
@ -9784,16 +9786,33 @@ void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
|
|||
" Expected target-based directive.");
|
||||
}
|
||||
|
||||
void CGOpenMPRuntime::checkArchForUnifiedAddressing(
|
||||
const OMPRequiresDecl *D) {
|
||||
void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
|
||||
for (const OMPClause *Clause : D->clauselists()) {
|
||||
if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
|
||||
HasRequiresUnifiedSharedMemory = true;
|
||||
break;
|
||||
} else if (const auto *AC =
|
||||
dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
|
||||
switch (AC->getAtomicDefaultMemOrderKind()) {
|
||||
case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
|
||||
RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease;
|
||||
break;
|
||||
case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
|
||||
RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
|
||||
break;
|
||||
case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
|
||||
RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
|
||||
break;
|
||||
case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const {
|
||||
return RequiresAtomicOrdering;
|
||||
}
|
||||
|
||||
bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
|
||||
LangAS &AS) {
|
||||
if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/Support/AtomicOrdering.h"
|
||||
|
||||
namespace llvm {
|
||||
class ArrayType;
|
||||
|
@ -704,6 +705,9 @@ private:
|
|||
/// directive is present.
|
||||
bool HasRequiresUnifiedSharedMemory = false;
|
||||
|
||||
/// Atomic ordering from the omp requires directive.
|
||||
llvm::AtomicOrdering RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
|
||||
|
||||
/// Flag for keeping track of weather a target region has been emitted.
|
||||
bool HasEmittedTargetRegion = false;
|
||||
|
||||
|
@ -1700,7 +1704,10 @@ public:
|
|||
|
||||
/// Perform check on requires decl to ensure that target architecture
|
||||
/// supports unified addressing
|
||||
virtual void checkArchForUnifiedAddressing(const OMPRequiresDecl *D);
|
||||
virtual void processRequiresDirective(const OMPRequiresDecl *D);
|
||||
|
||||
/// Gets default memory ordering as specified in requires directive.
|
||||
llvm::AtomicOrdering getDefaultMemoryOrdering() const;
|
||||
|
||||
/// Checks if the variable has associated OMPAllocateDeclAttr attribute with
|
||||
/// the predefined allocator and translates it into the corresponding address
|
||||
|
|
|
@ -4962,7 +4962,7 @@ static CudaArch getCudaArch(CodeGenModule &CGM) {
|
|||
|
||||
/// Check to see if target architecture supports unified addressing which is
|
||||
/// a restriction for OpenMP requires clause "unified_shared_memory".
|
||||
void CGOpenMPRuntimeNVPTX::checkArchForUnifiedAddressing(
|
||||
void CGOpenMPRuntimeNVPTX::processRequiresDirective(
|
||||
const OMPRequiresDecl *D) {
|
||||
for (const OMPClause *Clause : D->clauselists()) {
|
||||
if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
|
||||
|
@ -5017,7 +5017,7 @@ void CGOpenMPRuntimeNVPTX::checkArchForUnifiedAddressing(
|
|||
}
|
||||
}
|
||||
}
|
||||
CGOpenMPRuntime::checkArchForUnifiedAddressing(D);
|
||||
CGOpenMPRuntime::processRequiresDirective(D);
|
||||
}
|
||||
|
||||
/// Get number of SMs and number of blocks per SM.
|
||||
|
|
|
@ -395,7 +395,7 @@ public:
|
|||
|
||||
/// Perform check on requires decl to ensure that target architecture
|
||||
/// supports unified addressing
|
||||
void checkArchForUnifiedAddressing(const OMPRequiresDecl *D) override;
|
||||
void processRequiresDirective(const OMPRequiresDecl *D) override;
|
||||
|
||||
/// Returns default address space for the constant firstprivates, __constant__
|
||||
/// address space by default.
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "clang/Basic/PrettyStackTrace.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Support/AtomicOrdering.h"
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
using namespace llvm::omp;
|
||||
|
@ -4542,16 +4543,23 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
|||
|
||||
void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
|
||||
llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic;
|
||||
if (S.getSingleClause<OMPSeqCstClause>())
|
||||
bool MemOrderingSpecified = false;
|
||||
if (S.getSingleClause<OMPSeqCstClause>()) {
|
||||
AO = llvm::AtomicOrdering::SequentiallyConsistent;
|
||||
else if (S.getSingleClause<OMPAcqRelClause>())
|
||||
MemOrderingSpecified = true;
|
||||
} else if (S.getSingleClause<OMPAcqRelClause>()) {
|
||||
AO = llvm::AtomicOrdering::AcquireRelease;
|
||||
else if (S.getSingleClause<OMPAcquireClause>())
|
||||
MemOrderingSpecified = true;
|
||||
} else if (S.getSingleClause<OMPAcquireClause>()) {
|
||||
AO = llvm::AtomicOrdering::Acquire;
|
||||
else if (S.getSingleClause<OMPReleaseClause>())
|
||||
MemOrderingSpecified = true;
|
||||
} else if (S.getSingleClause<OMPReleaseClause>()) {
|
||||
AO = llvm::AtomicOrdering::Release;
|
||||
else if (S.getSingleClause<OMPRelaxedClause>())
|
||||
MemOrderingSpecified = true;
|
||||
} else if (S.getSingleClause<OMPRelaxedClause>()) {
|
||||
AO = llvm::AtomicOrdering::Monotonic;
|
||||
MemOrderingSpecified = true;
|
||||
}
|
||||
OpenMPClauseKind Kind = OMPC_unknown;
|
||||
for (const OMPClause *C : S.clauses()) {
|
||||
// Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
|
||||
|
@ -4565,6 +4573,23 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!MemOrderingSpecified) {
|
||||
llvm::AtomicOrdering DefaultOrder =
|
||||
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
|
||||
if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
|
||||
DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
|
||||
(DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
|
||||
Kind == OMPC_capture)) {
|
||||
AO = DefaultOrder;
|
||||
} else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
|
||||
if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
|
||||
AO = llvm::AtomicOrdering::Release;
|
||||
} else if (Kind == OMPC_read) {
|
||||
assert(Kind == OMPC_read && "Unexpected atomic kind.");
|
||||
AO = llvm::AtomicOrdering::Acquire;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
|
||||
if (const auto *FE = dyn_cast<FullExpr>(CS))
|
||||
|
|
|
@ -1473,7 +1473,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
|||
Actions.EndOpenMPClause();
|
||||
}
|
||||
// Consume final annot_pragma_openmp_end
|
||||
if (Clauses.size() == 0) {
|
||||
if (Clauses.empty()) {
|
||||
Diag(Tok, diag::err_omp_expected_clause)
|
||||
<< getOpenMPDirectiveName(OMPD_requires);
|
||||
ConsumeAnnotationToken();
|
||||
|
|
|
@ -271,6 +271,7 @@ private:
|
|||
nullptr};
|
||||
/// Vector of previously encountered target directives
|
||||
SmallVector<SourceLocation, 2> TargetLocations;
|
||||
SourceLocation AtomicLocation;
|
||||
|
||||
public:
|
||||
explicit DSAStackTy(Sema &S) : SemaRef(S) {}
|
||||
|
@ -555,7 +556,7 @@ public:
|
|||
|
||||
/// Checks if the defined 'requires' directive has specified type of clause.
|
||||
template <typename ClauseType>
|
||||
bool hasRequiresDeclWithClause() {
|
||||
bool hasRequiresDeclWithClause() const {
|
||||
return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
|
||||
return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
|
||||
return isa<ClauseType>(C);
|
||||
|
@ -590,6 +591,18 @@ public:
|
|||
TargetLocations.push_back(LocStart);
|
||||
}
|
||||
|
||||
/// Add location for the first encountered atomicc directive.
|
||||
void addAtomicDirectiveLoc(SourceLocation Loc) {
|
||||
if (AtomicLocation.isInvalid())
|
||||
AtomicLocation = Loc;
|
||||
}
|
||||
|
||||
/// Returns the location of the first encountered atomic directive in the
|
||||
/// module.
|
||||
SourceLocation getAtomicDirectiveLoc() const {
|
||||
return AtomicLocation;
|
||||
}
|
||||
|
||||
// Return previously encountered target region locations.
|
||||
ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
|
||||
return TargetLocations;
|
||||
|
@ -2830,18 +2843,26 @@ OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
|
|||
/// current compilation unit.
|
||||
ArrayRef<SourceLocation> TargetLocations =
|
||||
DSAStack->getEncounteredTargetLocs();
|
||||
if (!TargetLocations.empty()) {
|
||||
SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
|
||||
if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
|
||||
for (const OMPClause *CNew : ClauseList) {
|
||||
// Check if any of the requires clauses affect target regions.
|
||||
if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
|
||||
isa<OMPUnifiedAddressClause>(CNew) ||
|
||||
isa<OMPReverseOffloadClause>(CNew) ||
|
||||
isa<OMPDynamicAllocatorsClause>(CNew)) {
|
||||
Diag(Loc, diag::err_omp_target_before_requires)
|
||||
<< getOpenMPClauseName(CNew->getClauseKind());
|
||||
Diag(Loc, diag::err_omp_directive_before_requires)
|
||||
<< "target" << getOpenMPClauseName(CNew->getClauseKind());
|
||||
for (SourceLocation TargetLoc : TargetLocations) {
|
||||
Diag(TargetLoc, diag::note_omp_requires_encountered_target);
|
||||
Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
|
||||
<< "target";
|
||||
}
|
||||
} else if (!AtomicLoc.isInvalid() &&
|
||||
isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
|
||||
Diag(Loc, diag::err_omp_directive_before_requires)
|
||||
<< "atomic" << getOpenMPClauseName(CNew->getClauseKind());
|
||||
Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
|
||||
<< "atomic";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8926,6 +8947,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
|
|||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
// Register location of the first atomic directive.
|
||||
DSAStack->addAtomicDirectiveLoc(StartLoc);
|
||||
if (!AStmt)
|
||||
return StmtError();
|
||||
|
||||
|
|
|
@ -2840,7 +2840,8 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
|
|||
isa<PragmaDetectMismatchDecl>(D))
|
||||
return true;
|
||||
if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D) ||
|
||||
isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D))
|
||||
isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D) ||
|
||||
isa<OMPRequiresDecl>(D))
|
||||
return !D->getDeclContext()->isFunctionOrMethod();
|
||||
if (const auto *Var = dyn_cast<VarDecl>(D))
|
||||
return Var->isFileVarDecl() &&
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -triple x86_64-apple-darwin10 -x c++ -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -triple x86_64-apple-darwin10
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -verify %s -triple x86_64-apple-darwin10 -x c++ -emit-llvm -o -| FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd %s -fopenmp-version=50 -x c++ -emit-llvm -triple x86_64-apple-darwin10 -o -| FileCheck %s --check-prefix SIMD-ONLY0
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -triple x86_64-apple-darwin10
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -verify %s -emit-llvm -x c++ -emit-llvm -triple x86_64-apple-darwin10 -o -| FileCheck %s --check-prefix SIMD-ONLY0
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
#pragma omp requires atomic_default_mem_order(acq_rel)
|
||||
|
||||
// CHECK-LABEL: foo
|
||||
void foo() {
|
||||
int a = 0, b = 0;
|
||||
// CHECK: load atomic i32,{{.*}}acquire
|
||||
#pragma omp atomic read
|
||||
a = b;
|
||||
// CHECK: store atomic i32{{.*}}release
|
||||
#pragma omp atomic write
|
||||
a = b;
|
||||
// CHECK: atomicrmw add i32{{.*}}release
|
||||
#pragma omp atomic
|
||||
a += 1;
|
||||
// CHECK: atomicrmw add i32{{.*}}release
|
||||
#pragma omp atomic update
|
||||
a += 1;
|
||||
// CHECK: atomicrmw add i32{{.*}}acq_rel
|
||||
#pragma omp atomic capture
|
||||
{
|
||||
b = a;
|
||||
a += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
|
||||
|
||||
void foo2() {
|
||||
int a;
|
||||
#pragma omp atomic update // expected-note 3 {{'atomic' previously encountered here}}
|
||||
a = a + 1;
|
||||
}
|
||||
|
||||
#pragma omp requires atomic_default_mem_order(seq_cst) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-note 2 {{atomic_default_mem_order clause previously used here}}
|
||||
#pragma omp requires atomic_default_mem_order(acq_rel) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
|
||||
#pragma omp requires atomic_default_mem_order(relaxed) // expected-error {{'atomic' region encountered before requires directive with 'atomic_default_mem_order' clause}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
|
||||
#pragma omp requires atomic_default_mem_order(release) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
|
|
@ -0,0 +1,39 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -triple x86_64-apple-darwin10 -x c++ -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -triple x86_64-apple-darwin10
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -verify %s -triple x86_64-apple-darwin10 -x c++ -emit-llvm -o -| FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd %s -fopenmp-version=50 -x c++ -emit-llvm -triple x86_64-apple-darwin10 -o -| FileCheck %s --check-prefix SIMD-ONLY0
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -triple x86_64-apple-darwin10
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -verify %s -emit-llvm -x c++ -emit-llvm -triple x86_64-apple-darwin10 -o -| FileCheck %s --check-prefix SIMD-ONLY0
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
#pragma omp requires atomic_default_mem_order(relaxed)
|
||||
|
||||
// CHECK-LABEL: foo
|
||||
void foo() {
|
||||
int a = 0, b = 0;
|
||||
// CHECK: load atomic i32,{{.*}}monotonic
|
||||
#pragma omp atomic read
|
||||
a = b;
|
||||
// CHECK: store atomic i32{{.*}}monotonic
|
||||
#pragma omp atomic write
|
||||
a = b;
|
||||
// CHECK: atomicrmw add i32{{.*}}monotonic
|
||||
#pragma omp atomic
|
||||
a += 1;
|
||||
// CHECK: atomicrmw add i32{{.*}}monotonic
|
||||
#pragma omp atomic update
|
||||
a += 1;
|
||||
// CHECK: atomicrmw add i32{{.*}}monotonic
|
||||
#pragma omp atomic capture
|
||||
{
|
||||
b = a;
|
||||
a += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,39 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 %s -triple x86_64-apple-darwin10 -x c++ -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -triple x86_64-apple-darwin10
|
||||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -verify %s -triple x86_64-apple-darwin10 -x c++ -emit-llvm -o -| FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd %s -fopenmp-version=50 -x c++ -emit-llvm -triple x86_64-apple-darwin10 -o -| FileCheck %s --check-prefix SIMD-ONLY0
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -triple x86_64-apple-darwin10
|
||||
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -verify %s -emit-llvm -x c++ -emit-llvm -triple x86_64-apple-darwin10 -o -| FileCheck %s --check-prefix SIMD-ONLY0
|
||||
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
#pragma omp requires atomic_default_mem_order(seq_cst)
|
||||
|
||||
// CHECK-LABEL: foo
|
||||
void foo() {
|
||||
int a = 0, b = 0;
|
||||
// CHECK: load atomic i32,{{.*}}seq_cst
|
||||
#pragma omp atomic read
|
||||
a = b;
|
||||
// CHECK: store atomic i32{{.*}}seq_cst
|
||||
#pragma omp atomic write
|
||||
a = b;
|
||||
// CHECK: atomicrmw add i32{{.*}}seq_cst
|
||||
#pragma omp atomic
|
||||
a += 1;
|
||||
// CHECK: atomicrmw add i32{{.*}}seq_cst
|
||||
#pragma omp atomic update
|
||||
a += 1;
|
||||
// CHECK: atomicrmw add i32{{.*}}seq_cst
|
||||
#pragma omp atomic capture
|
||||
{
|
||||
b = a;
|
||||
a += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
void foo2() {
|
||||
int a;
|
||||
#pragma omp target // expected-note 4 {{target previously encountered here}}
|
||||
#pragma omp target // expected-note 4 {{'target' previously encountered here}}
|
||||
{
|
||||
a = a + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma omp requires atomic_default_mem_order(seq_cst)
|
||||
#pragma omp requires unified_address //expected-error {{target region encountered before requires directive with 'unified_address' clause}}
|
||||
#pragma omp requires unified_shared_memory //expected-error {{target region encountered before requires directive with 'unified_shared_memory' clause}}
|
||||
#pragma omp requires reverse_offload //expected-error {{target region encountered before requires directive with 'reverse_offload' clause}}
|
||||
#pragma omp requires dynamic_allocators //expected-error {{target region encountered before requires directive with 'dynamic_allocators' clause}}
|
||||
#pragma omp requires unified_address //expected-error {{'target' region encountered before requires directive with 'unified_address' clause}}
|
||||
#pragma omp requires unified_shared_memory //expected-error {{'target' region encountered before requires directive with 'unified_shared_memory' clause}}
|
||||
#pragma omp requires reverse_offload //expected-error {{'target' region encountered before requires directive with 'reverse_offload' clause}}
|
||||
#pragma omp requires dynamic_allocators //expected-error {{'target' region encountered before requires directive with 'dynamic_allocators' clause}}
|
||||
|
|
Loading…
Reference in New Issue