[OpenACC] allow 'if' clause on 'atomic' construct
This was added in OpenACC PR #511 in the 3.4 branch. From an AST/Sema perspective this is pretty trivial as the infrastructure for 'if' already exists, however the atomic construct needed to be taught to take clauses. This patch does that and adds some testing to do so.
This commit is contained in:
@@ -829,24 +829,42 @@ public:
|
||||
|
||||
// This class represents the 'atomic' construct, which has an associated
|
||||
// statement, but no clauses.
|
||||
class OpenACCAtomicConstruct final : public OpenACCAssociatedStmtConstruct {
|
||||
class OpenACCAtomicConstruct final
|
||||
: public OpenACCAssociatedStmtConstruct,
|
||||
private llvm::TrailingObjects<OpenACCAtomicConstruct,
|
||||
const OpenACCClause *> {
|
||||
|
||||
friend class ASTStmtReader;
|
||||
friend TrailingObjects;
|
||||
OpenACCAtomicKind AtomicKind = OpenACCAtomicKind::None;
|
||||
|
||||
OpenACCAtomicConstruct(EmptyShell)
|
||||
OpenACCAtomicConstruct(unsigned NumClauses)
|
||||
: OpenACCAssociatedStmtConstruct(
|
||||
OpenACCAtomicConstructClass, OpenACCDirectiveKind::Atomic,
|
||||
SourceLocation{}, SourceLocation{}, SourceLocation{},
|
||||
/*AssociatedStmt=*/nullptr) {}
|
||||
/*AssociatedStmt=*/nullptr) {
|
||||
std::uninitialized_value_construct(
|
||||
getTrailingObjects<const OpenACCClause *>(),
|
||||
getTrailingObjects<const OpenACCClause *>() + NumClauses);
|
||||
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
|
||||
NumClauses));
|
||||
}
|
||||
|
||||
OpenACCAtomicConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
OpenACCAtomicKind AtKind, SourceLocation End,
|
||||
ArrayRef<const OpenACCClause *> Clauses,
|
||||
Stmt *AssociatedStmt)
|
||||
: OpenACCAssociatedStmtConstruct(OpenACCAtomicConstructClass,
|
||||
OpenACCDirectiveKind::Atomic, Start,
|
||||
DirectiveLoc, End, AssociatedStmt),
|
||||
AtomicKind(AtKind) {}
|
||||
AtomicKind(AtKind) {
|
||||
// Initialize the trailing storage.
|
||||
std::uninitialized_copy(Clauses.begin(), Clauses.end(),
|
||||
getTrailingObjects<const OpenACCClause *>());
|
||||
|
||||
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
|
||||
Clauses.size()));
|
||||
}
|
||||
|
||||
void setAssociatedStmt(Stmt *S) {
|
||||
OpenACCAssociatedStmtConstruct::setAssociatedStmt(S);
|
||||
@@ -857,10 +875,12 @@ public:
|
||||
return T->getStmtClass() == OpenACCAtomicConstructClass;
|
||||
}
|
||||
|
||||
static OpenACCAtomicConstruct *CreateEmpty(const ASTContext &C);
|
||||
static OpenACCAtomicConstruct *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses);
|
||||
static OpenACCAtomicConstruct *
|
||||
Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt);
|
||||
OpenACCAtomicKind AtKind, SourceLocation End,
|
||||
ArrayRef<const OpenACCClause *> Clauses, Stmt *AssociatedStmt);
|
||||
|
||||
OpenACCAtomicKind getAtomicKind() const { return AtomicKind; }
|
||||
const Stmt *getAssociatedStmt() const {
|
||||
|
||||
@@ -307,20 +307,26 @@ OpenACCUpdateConstruct::Create(const ASTContext &C, SourceLocation Start,
|
||||
}
|
||||
|
||||
OpenACCAtomicConstruct *
|
||||
OpenACCAtomicConstruct::CreateEmpty(const ASTContext &C) {
|
||||
void *Mem = C.Allocate(sizeof(OpenACCAtomicConstruct));
|
||||
auto *Inst = new (Mem) OpenACCAtomicConstruct(EmptyShell{});
|
||||
OpenACCAtomicConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
|
||||
void *Mem = C.Allocate(
|
||||
OpenACCAtomicConstruct::totalSizeToAlloc<const OpenACCClause *>(
|
||||
NumClauses));
|
||||
auto *Inst = new (Mem) OpenACCAtomicConstruct(NumClauses);
|
||||
return Inst;
|
||||
}
|
||||
|
||||
OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create(
|
||||
const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt) {
|
||||
void *Mem = C.Allocate(sizeof(OpenACCAtomicConstruct));
|
||||
auto *Inst = new (Mem)
|
||||
OpenACCAtomicConstruct(Start, DirectiveLoc, AtKind, End, AssociatedStmt);
|
||||
OpenACCAtomicKind AtKind, SourceLocation End,
|
||||
ArrayRef<const OpenACCClause *> Clauses, Stmt *AssociatedStmt) {
|
||||
void *Mem = C.Allocate(
|
||||
OpenACCAtomicConstruct::totalSizeToAlloc<const OpenACCClause *>(
|
||||
Clauses.size()));
|
||||
auto *Inst = new (Mem) OpenACCAtomicConstruct(Start, DirectiveLoc, AtKind,
|
||||
End, Clauses, AssociatedStmt);
|
||||
return Inst;
|
||||
}
|
||||
|
||||
OpenACCCacheConstruct *OpenACCCacheConstruct::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumVars) {
|
||||
void *Mem =
|
||||
|
||||
@@ -1258,6 +1258,7 @@ void StmtPrinter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
|
||||
if (S->getAtomicKind() != OpenACCAtomicKind::None)
|
||||
OS << " " << S->getAtomicKind();
|
||||
|
||||
PrintOpenACCClauseList(S);
|
||||
OS << '\n';
|
||||
PrintStmt(S->getAssociatedStmt());
|
||||
}
|
||||
|
||||
@@ -2839,6 +2839,8 @@ void StmtProfiler::VisitOpenACCUpdateConstruct(
|
||||
void StmtProfiler::VisitOpenACCAtomicConstruct(
|
||||
const OpenACCAtomicConstruct *S) {
|
||||
VisitStmt(S);
|
||||
OpenACCClauseProfiler P{*this};
|
||||
P.VisitOpenACCClauseList(S->clauses());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) {
|
||||
|
||||
@@ -1832,9 +1832,8 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(
|
||||
EndLoc, Clauses);
|
||||
}
|
||||
case OpenACCDirectiveKind::Atomic: {
|
||||
assert(Clauses.empty() && "Atomic doesn't allow clauses");
|
||||
return OpenACCAtomicConstruct::Create(
|
||||
getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc,
|
||||
getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc, Clauses,
|
||||
AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
|
||||
}
|
||||
case OpenACCDirectiveKind::Cache: {
|
||||
|
||||
@@ -55,6 +55,8 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
|
||||
case OpenACCDirectiveKind::ParallelLoop:
|
||||
case OpenACCDirectiveKind::SerialLoop:
|
||||
case OpenACCDirectiveKind::KernelsLoop:
|
||||
// OpenACC 3.4(prerelease) PR #511 adds 'if' to atomic.
|
||||
case OpenACCDirectiveKind::Atomic:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -4222,10 +4222,11 @@ public:
|
||||
SourceLocation DirLoc,
|
||||
OpenACCAtomicKind AtKind,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<OpenACCClause *> Clauses,
|
||||
StmtResult AssociatedStmt) {
|
||||
return getSema().OpenACC().ActOnEndStmtDirective(
|
||||
OpenACCDirectiveKind::Atomic, BeginLoc, DirLoc, SourceLocation{},
|
||||
SourceLocation{}, {}, AtKind, SourceLocation{}, EndLoc, {},
|
||||
SourceLocation{}, {}, AtKind, SourceLocation{}, EndLoc, Clauses,
|
||||
AssociatedStmt);
|
||||
}
|
||||
|
||||
@@ -12744,6 +12745,10 @@ StmtResult TreeTransform<Derived>::TransformOpenACCAtomicConstruct(
|
||||
OpenACCAtomicConstruct *C) {
|
||||
getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc());
|
||||
|
||||
llvm::SmallVector<OpenACCClause *> TransformedClauses =
|
||||
getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
|
||||
C->clauses());
|
||||
|
||||
if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),
|
||||
C->getBeginLoc(), {}))
|
||||
return StmtError();
|
||||
@@ -12759,7 +12764,7 @@ StmtResult TreeTransform<Derived>::TransformOpenACCAtomicConstruct(
|
||||
|
||||
return getDerived().RebuildOpenACCAtomicConstruct(
|
||||
C->getBeginLoc(), C->getDirectiveLoc(), C->getAtomicKind(),
|
||||
C->getEndLoc(), AssocStmt);
|
||||
C->getEndLoc(), TransformedClauses, AssocStmt);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
|
||||
@@ -2940,9 +2940,7 @@ void ASTStmtReader::VisitOpenACCCacheConstruct(OpenACCCacheConstruct *S) {
|
||||
|
||||
void ASTStmtReader::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
|
||||
VisitStmt(S);
|
||||
S->Kind = Record.readEnum<OpenACCDirectiveKind>();
|
||||
S->Range = Record.readSourceRange();
|
||||
S->DirectiveLoc = Record.readSourceLocation();
|
||||
VisitOpenACCConstructStmt(S);
|
||||
S->AtomicKind = Record.readEnum<OpenACCAtomicKind>();
|
||||
S->setAssociatedStmt(Record.readSubStmt());
|
||||
}
|
||||
@@ -4490,7 +4488,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
break;
|
||||
}
|
||||
case STMT_OPENACC_ATOMIC_CONSTRUCT: {
|
||||
S = OpenACCAtomicConstruct::CreateEmpty(Context);
|
||||
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
|
||||
S = OpenACCAtomicConstruct::CreateEmpty(Context, NumClauses);
|
||||
break;
|
||||
}
|
||||
case EXPR_REQUIRES: {
|
||||
|
||||
@@ -3014,9 +3014,7 @@ void ASTStmtWriter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
|
||||
|
||||
void ASTStmtWriter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
|
||||
VisitStmt(S);
|
||||
Record.writeEnum(S->Kind);
|
||||
Record.AddSourceRange(S->Range);
|
||||
Record.AddSourceLocation(S->DirectiveLoc);
|
||||
VisitOpenACCConstructStmt(S);
|
||||
Record.writeEnum(S->getAtomicKind());
|
||||
Record.AddStmt(S->getAssociatedStmt());
|
||||
|
||||
|
||||
@@ -31,3 +31,35 @@ void foo(int v, int x) {
|
||||
{ x--; v = x; }
|
||||
|
||||
}
|
||||
|
||||
void foo2(int v, int x) {
|
||||
// CHECK: #pragma acc atomic read if(v)
|
||||
// CHECK-NEXT: v = x;
|
||||
#pragma acc atomic read if (v)
|
||||
v = x;
|
||||
// CHECK-NEXT: pragma acc atomic write if(x)
|
||||
// CHECK-NEXT: v = x + 1;
|
||||
#pragma acc atomic write if (x)
|
||||
v = x + 1;
|
||||
// CHECK-NEXT: pragma acc atomic update if(true)
|
||||
// CHECK-NEXT: x++;
|
||||
#pragma acc atomic update if (true)
|
||||
x++;
|
||||
// CHECK-NEXT: pragma acc atomic if(false)
|
||||
// CHECK-NEXT: x--;
|
||||
#pragma acc atomic if (false)
|
||||
x--;
|
||||
// CHECK-NEXT: pragma acc atomic capture if(v < x)
|
||||
// CHECK-NEXT: v = x++;
|
||||
#pragma acc atomic capture if (v < x)
|
||||
v = x++;
|
||||
|
||||
// CHECK-NEXT: #pragma acc atomic capture if(x > v)
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: x--;
|
||||
// CHECK-NEXT: v = x;
|
||||
// CHECK-NEXT: }
|
||||
#pragma acc atomic capture if (x > v)
|
||||
{ x--; v = x; }
|
||||
|
||||
}
|
||||
|
||||
@@ -1288,3 +1288,27 @@ void BCP1();
|
||||
#pragma acc routine seq bind("ReductionClauseParsing")
|
||||
|
||||
#pragma acc routine(BCP1) seq bind(unknown_thing)
|
||||
|
||||
void AtomicIf() {
|
||||
int i, j;
|
||||
// expected-error@+1{{expected '('}}
|
||||
#pragma acc atomic read if
|
||||
i = j;
|
||||
#pragma acc atomic read if (0)
|
||||
i = j;
|
||||
#pragma acc atomic write if (1)
|
||||
i = j + 1;
|
||||
|
||||
#pragma acc atomic update if (i)
|
||||
++i;
|
||||
#pragma acc atomic if (j)
|
||||
++i;
|
||||
|
||||
#pragma acc atomic capture if (0)
|
||||
i = j++;
|
||||
#pragma acc atomic capture if (i)
|
||||
{
|
||||
++j;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,3 +61,27 @@ void use() {
|
||||
void another_func();
|
||||
// expected-warning@+1{{encoding prefix 'U' on an unevaluated string literal has no effect}}
|
||||
#pragma acc routine(another_func) seq bind(U"32 bits")
|
||||
|
||||
void AtomicIf() {
|
||||
int i, j;
|
||||
// expected-error@+1{{expected '('}}
|
||||
#pragma acc atomic read if
|
||||
i = j;
|
||||
#pragma acc atomic read if (true)
|
||||
i = j;
|
||||
#pragma acc atomic write if (false)
|
||||
i = j + 1;
|
||||
|
||||
#pragma acc atomic update if (i)
|
||||
++i;
|
||||
#pragma acc atomic if (j)
|
||||
++i;
|
||||
|
||||
#pragma acc atomic capture if (true)
|
||||
i = j++;
|
||||
#pragma acc atomic capture if (i)
|
||||
{
|
||||
++j;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,90 @@ _Pragma("acc atomic read")
|
||||
#pragma acc atomic capture
|
||||
{ x--; v = x; }
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic read
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
#pragma acc atomic read if (v < x)
|
||||
v = x;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic write
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'int' '+'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
_Pragma("acc atomic write if (v < x)")
|
||||
v = x + 1;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic update
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '++'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
#pragma acc atomic update if (v < x)
|
||||
x++;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic <none>
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '--'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
#pragma acc atomic if (v < x)
|
||||
x--;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic capture
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '++'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
#pragma acc atomic capture if (v < x)
|
||||
v = x++;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic capture
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '--'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
#pragma acc atomic capture if (v < x)
|
||||
{ x--; v = x; }
|
||||
}
|
||||
|
||||
template<typename T, int I>
|
||||
@@ -124,6 +208,76 @@ void templ_foo(T v, T x) {
|
||||
#pragma acc atomic capture
|
||||
{ x--; v = x; }
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic read
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} '<dependent type>' '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
#pragma acc atomic read if (v < x)
|
||||
v = x;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic write
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} '<dependent type>' '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '+'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'I' 'int'
|
||||
_Pragma("acc atomic write if (v < x)")
|
||||
v = x + I;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic update
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} '<dependent type>' postfix '++'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
#pragma acc atomic update if (v < x)
|
||||
x++;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic <none>
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} '<dependent type>' postfix '--'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
#pragma acc atomic if (v < x)
|
||||
x--;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic capture
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} '<dependent type>' '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} '<dependent type>' postfix '++'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
#pragma acc atomic capture if (v < x)
|
||||
v = x++;
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic capture
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} '<dependent type>' postfix '--'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} '<dependent type>' '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'T'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'T'
|
||||
#pragma acc atomic capture if (v < x)
|
||||
{ x--; v = x; }
|
||||
|
||||
// CHECK-NEXT: FunctionDecl{{.*}} templ_foo 'void (int, int)' implicit_instantiation
|
||||
// CHECK-NEXT: TemplateArgument type 'int'
|
||||
// CHECK-NEXT: BuiltinType{{.*}} 'int'
|
||||
@@ -170,6 +324,81 @@ void templ_foo(T v, T x) {
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic read
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic write
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'int' '+'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: SubstNonTypeTemplateParmExpr{{.*}} 'int'
|
||||
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int'{{.*}}I
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic update
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '++'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic <none>
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '--'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic capture
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '++'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
|
||||
// CHECK-NEXT: OpenACCAtomicConstruct{{.*}} atomic capture
|
||||
// CHECK-NEXT: if clause
|
||||
// CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: UnaryOperator{{.*}} 'int' postfix '--'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
// CHECK-NEXT: BinaryOperator{{.*}} 'int' lvalue '='
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'v' 'int'
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int' <LValueToRValue>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'x' 'int'
|
||||
}
|
||||
|
||||
void use() {
|
||||
|
||||
@@ -47,9 +47,30 @@ Struct &operator-(Struct&, Struct&);
|
||||
|
||||
Struct S1, S2;
|
||||
|
||||
struct NotCondition{} NC;
|
||||
|
||||
template<typename T>
|
||||
T &getRValue();
|
||||
|
||||
void IfClause(int x, int v) {
|
||||
// expected-error@+1{{OpenACC 'seq' clause is not valid on 'atomic' directive}}
|
||||
#pragma acc atomic read seq
|
||||
x = v;
|
||||
|
||||
// expected-error@+1{{expected '('}}
|
||||
#pragma acc atomic read if
|
||||
x = v;
|
||||
|
||||
// expected-error@+1{{value of type 'struct NotCondition' is not contextually convertible to 'bool'}}
|
||||
#pragma acc atomic read if(NC)
|
||||
x = v;
|
||||
|
||||
// expected-error@+2{{OpenACC 'if' clause cannot appear more than once on a 'atomic' directive}}
|
||||
// expected-note@+1{{previous clause is here}}
|
||||
#pragma acc atomic read if(x) if (v)
|
||||
x = v;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void AtomicReadTemplate(T LHS, T RHS) {
|
||||
#pragma acc atomic read
|
||||
|
||||
@@ -3719,6 +3719,8 @@ void EnqueueVisitor::VisitOpenACCUpdateConstruct(
|
||||
void EnqueueVisitor::VisitOpenACCAtomicConstruct(
|
||||
const OpenACCAtomicConstruct *C) {
|
||||
EnqueueChildren(C);
|
||||
for (auto *Clause : C->clauses())
|
||||
EnqueueChildren(Clause);
|
||||
}
|
||||
|
||||
void EnqueueVisitor::VisitAnnotateAttr(const AnnotateAttr *A) {
|
||||
|
||||
Reference in New Issue
Block a user