mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 01:46:49 +00:00
[OpenACC] Enable 'self' sema for 'update' construct
The 'self' clause is an unfortunately difficult one, as it has a significantly different meaning between 'update' and the other constructs. This patch introduces a way for the 'self' clause to work as both. I considered making this two separate AST nodes (one for 'self' on 'update' and one for the others), however this makes the automated macros/etc for supporting a clause break. Instead, 'self' has the ability to act as either a condition or as a var-list clause. As this is the only one of its kind, it is implemented all within it. If in the future we have more that work like this, we should consider rewriting a lot of the macros that we use to make clauses work, and make them separate ast nodes.
This commit is contained in:
parent
ac08f0dfef
commit
2c2accbcc6
@ -327,18 +327,89 @@ public:
|
||||
SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// A 'self' clause, which has an optional condition expression.
|
||||
class OpenACCSelfClause : public OpenACCClauseWithCondition {
|
||||
/// A 'self' clause, which has an optional condition expression, or, in the
|
||||
/// event of an 'update' directive, contains a 'VarList'.
|
||||
class OpenACCSelfClause final
|
||||
: public OpenACCClauseWithParams,
|
||||
private llvm::TrailingObjects<OpenACCSelfClause, Expr *> {
|
||||
friend TrailingObjects;
|
||||
// Holds whether this HAS a condition expression. Lacks a value if this is NOT
|
||||
// a condition-expr self clause.
|
||||
std::optional<bool> HasConditionExpr;
|
||||
// Holds the number of stored expressions. In the case of a condition-expr
|
||||
// self clause, this is expected to be ONE (and there to be 1 trailing
|
||||
// object), whether or not that is null.
|
||||
unsigned NumExprs;
|
||||
|
||||
OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr, SourceLocation EndLoc);
|
||||
OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
|
||||
|
||||
// Intentionally internal, meant to be an implementation detail of everything
|
||||
// else. All non-internal uses should go through getConditionExpr/getVarList.
|
||||
llvm::ArrayRef<Expr *> getExprs() const {
|
||||
return {getTrailingObjects<Expr *>(), NumExprs};
|
||||
}
|
||||
|
||||
public:
|
||||
static bool classof(const OpenACCClause *C) {
|
||||
return C->getClauseKind() == OpenACCClauseKind::Self;
|
||||
}
|
||||
|
||||
bool isConditionExprClause() const { return HasConditionExpr.has_value(); }
|
||||
|
||||
bool hasConditionExpr() const {
|
||||
assert(HasConditionExpr.has_value() &&
|
||||
"VarList Self Clause asked about condition expression");
|
||||
return *HasConditionExpr;
|
||||
}
|
||||
|
||||
const Expr *getConditionExpr() const {
|
||||
assert(HasConditionExpr.has_value() &&
|
||||
"VarList Self Clause asked about condition expression");
|
||||
assert(getExprs().size() == 1 &&
|
||||
"ConditionExpr Self Clause with too many Exprs");
|
||||
return getExprs()[0];
|
||||
}
|
||||
|
||||
Expr *getConditionExpr() {
|
||||
assert(HasConditionExpr.has_value() &&
|
||||
"VarList Self Clause asked about condition expression");
|
||||
assert(getExprs().size() == 1 &&
|
||||
"ConditionExpr Self Clause with too many Exprs");
|
||||
return getExprs()[0];
|
||||
}
|
||||
|
||||
ArrayRef<Expr *> getVarList() {
|
||||
assert(!HasConditionExpr.has_value() &&
|
||||
"Condition Expr self clause asked about var list");
|
||||
return getExprs();
|
||||
}
|
||||
ArrayRef<Expr *> getVarList() const {
|
||||
assert(!HasConditionExpr.has_value() &&
|
||||
"Condition Expr self clause asked about var list");
|
||||
return getExprs();
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(
|
||||
reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()),
|
||||
reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>() + NumExprs));
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
child_range Children = const_cast<OpenACCSelfClause *>(this)->children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr, SourceLocation EndLoc);
|
||||
static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> ConditionExpr,
|
||||
SourceLocation EndLoc);
|
||||
};
|
||||
|
||||
/// Represents a clause that has one or more expressions associated with it.
|
||||
|
@ -409,6 +409,8 @@ public:
|
||||
ClauseKind == OpenACCClauseKind::Detach ||
|
||||
ClauseKind == OpenACCClauseKind::DevicePtr ||
|
||||
ClauseKind == OpenACCClauseKind::Reduction ||
|
||||
(ClauseKind == OpenACCClauseKind::Self &&
|
||||
DirKind == OpenACCDirectiveKind::Update) ||
|
||||
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
|
||||
"Parsed clause kind does not have a var-list");
|
||||
|
||||
@ -551,6 +553,8 @@ public:
|
||||
ClauseKind == OpenACCClauseKind::UseDevice ||
|
||||
ClauseKind == OpenACCClauseKind::Detach ||
|
||||
ClauseKind == OpenACCClauseKind::DevicePtr ||
|
||||
(ClauseKind == OpenACCClauseKind::Self &&
|
||||
DirKind == OpenACCDirectiveKind::Update) ||
|
||||
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
|
||||
"Parsed clause kind does not have a var-list");
|
||||
assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
|
||||
@ -590,6 +594,8 @@ public:
|
||||
ClauseKind == OpenACCClauseKind::UseDevice ||
|
||||
ClauseKind == OpenACCClauseKind::Detach ||
|
||||
ClauseKind == OpenACCClauseKind::DevicePtr ||
|
||||
(ClauseKind == OpenACCClauseKind::Self &&
|
||||
DirKind == OpenACCDirectiveKind::Update) ||
|
||||
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
|
||||
"Parsed clause kind does not have a var-list");
|
||||
assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
|
||||
|
@ -20,7 +20,7 @@ using namespace clang;
|
||||
bool OpenACCClauseWithParams::classof(const OpenACCClause *C) {
|
||||
return OpenACCDeviceTypeClause::classof(C) ||
|
||||
OpenACCClauseWithCondition::classof(C) ||
|
||||
OpenACCClauseWithExprs::classof(C);
|
||||
OpenACCClauseWithExprs::classof(C) || OpenACCSelfClause::classof(C);
|
||||
}
|
||||
bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
|
||||
return OpenACCWaitClause::classof(C) || OpenACCNumGangsClause::classof(C) ||
|
||||
@ -41,7 +41,7 @@ bool OpenACCClauseWithVarList::classof(const OpenACCClause *C) {
|
||||
OpenACCReductionClause::classof(C) || OpenACCCreateClause::classof(C);
|
||||
}
|
||||
bool OpenACCClauseWithCondition::classof(const OpenACCClause *C) {
|
||||
return OpenACCIfClause::classof(C) || OpenACCSelfClause::classof(C);
|
||||
return OpenACCIfClause::classof(C);
|
||||
}
|
||||
bool OpenACCClauseWithSingleIntExpr::classof(const OpenACCClause *C) {
|
||||
return OpenACCNumWorkersClause::classof(C) ||
|
||||
@ -87,19 +87,43 @@ OpenACCSelfClause *OpenACCSelfClause::Create(const ASTContext &C,
|
||||
SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr,
|
||||
SourceLocation EndLoc) {
|
||||
void *Mem = C.Allocate(sizeof(OpenACCIfClause), alignof(OpenACCIfClause));
|
||||
void *Mem = C.Allocate(OpenACCSelfClause::totalSizeToAlloc<Expr *>(1));
|
||||
return new (Mem)
|
||||
OpenACCSelfClause(BeginLoc, LParenLoc, ConditionExpr, EndLoc);
|
||||
}
|
||||
|
||||
OpenACCSelfClause *OpenACCSelfClause::Create(const ASTContext &C,
|
||||
SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> VarList,
|
||||
SourceLocation EndLoc) {
|
||||
void *Mem =
|
||||
C.Allocate(OpenACCSelfClause::totalSizeToAlloc<Expr *>(VarList.size()));
|
||||
return new (Mem) OpenACCSelfClause(BeginLoc, LParenLoc, VarList, EndLoc);
|
||||
}
|
||||
|
||||
OpenACCSelfClause::OpenACCSelfClause(SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
llvm::ArrayRef<Expr *> VarList,
|
||||
SourceLocation EndLoc)
|
||||
: OpenACCClauseWithParams(OpenACCClauseKind::Self, BeginLoc, LParenLoc,
|
||||
EndLoc),
|
||||
HasConditionExpr(std::nullopt), NumExprs(VarList.size()) {
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(),
|
||||
getTrailingObjects<Expr *>());
|
||||
}
|
||||
|
||||
OpenACCSelfClause::OpenACCSelfClause(SourceLocation BeginLoc,
|
||||
SourceLocation LParenLoc,
|
||||
Expr *ConditionExpr, SourceLocation EndLoc)
|
||||
: OpenACCClauseWithCondition(OpenACCClauseKind::Self, BeginLoc, LParenLoc,
|
||||
ConditionExpr, EndLoc) {
|
||||
: OpenACCClauseWithParams(OpenACCClauseKind::Self, BeginLoc, LParenLoc,
|
||||
EndLoc),
|
||||
HasConditionExpr(ConditionExpr != nullptr), NumExprs(1) {
|
||||
assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
|
||||
ConditionExpr->getType()->isScalarType()) &&
|
||||
"Condition expression type not scalar/dependent");
|
||||
std::uninitialized_copy(&ConditionExpr, &ConditionExpr + 1,
|
||||
getTrailingObjects<Expr *>());
|
||||
}
|
||||
|
||||
OpenACCClause::child_range OpenACCClause::children() {
|
||||
@ -555,9 +579,17 @@ void OpenACCClausePrinter::VisitIfClause(const OpenACCIfClause &C) {
|
||||
|
||||
void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) {
|
||||
OS << "self";
|
||||
if (const Expr *CondExpr = C.getConditionExpr()) {
|
||||
|
||||
if (C.isConditionExprClause()) {
|
||||
if (const Expr *CondExpr = C.getConditionExpr()) {
|
||||
OS << "(";
|
||||
printExpr(CondExpr);
|
||||
OS << ")";
|
||||
}
|
||||
} else {
|
||||
OS << "(";
|
||||
printExpr(CondExpr);
|
||||
llvm::interleaveComma(C.getVarList(), OS,
|
||||
[&](const Expr *E) { printExpr(E); });
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
@ -2555,8 +2555,13 @@ void OpenACCClauseProfiler::VisitCreateClause(
|
||||
}
|
||||
|
||||
void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
|
||||
if (Clause.hasConditionExpr())
|
||||
Profiler.VisitStmt(Clause.getConditionExpr());
|
||||
if (Clause.isConditionExprClause()) {
|
||||
if (Clause.hasConditionExpr())
|
||||
Profiler.VisitStmt(Clause.getConditionExpr());
|
||||
} else {
|
||||
for (auto *E : Clause.getVarList())
|
||||
Profiler.VisitStmt(E);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenACCClauseProfiler::VisitFinalizeClause(
|
||||
|
@ -1003,7 +1003,9 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
|
||||
// the 'update' clause, so we have to handle it here. U se an assert to
|
||||
// make sure we get the right differentiator.
|
||||
assert(DirKind == OpenACCDirectiveKind::Update);
|
||||
[[fallthrough]];
|
||||
ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
|
||||
/*IsReadOnly=*/false, /*IsZero=*/false);
|
||||
break;
|
||||
case OpenACCClauseKind::Device:
|
||||
case OpenACCClauseKind::DeviceResident:
|
||||
case OpenACCClauseKind::Host:
|
||||
|
@ -736,14 +736,14 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
|
||||
// isn't really much to do here.
|
||||
|
||||
// If the 'if' clause is true, it makes the 'self' clause have no effect,
|
||||
// diagnose that here.
|
||||
// TODO OpenACC: When we add these two to other constructs, we might not
|
||||
// want to warn on this (for example, 'update').
|
||||
const auto *Itr =
|
||||
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
|
||||
if (Itr != ExistingClauses.end()) {
|
||||
SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
|
||||
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
|
||||
// diagnose that here. This only applies on compute/combined constructs.
|
||||
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Update) {
|
||||
const auto *Itr =
|
||||
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
|
||||
if (Itr != ExistingClauses.end()) {
|
||||
SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
|
||||
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
|
||||
}
|
||||
}
|
||||
|
||||
return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
|
||||
@ -753,16 +753,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
|
||||
|
||||
OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
|
||||
SemaOpenACC::OpenACCParsedClause &Clause) {
|
||||
// Restrictions only properly implemented on 'compute' constructs, and
|
||||
// 'compute' constructs are the only construct that can do anything with
|
||||
// this yet, so skip/treat as unimplemented in this case.
|
||||
if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
|
||||
return isNotImplemented();
|
||||
|
||||
// TODO OpenACC: When we implement this for 'update', this takes a
|
||||
// 'var-list' instead of a condition expression, so semantics/handling has
|
||||
// to happen differently here.
|
||||
|
||||
// There is no prose in the standard that says duplicates aren't allowed,
|
||||
// but this diagnostic is present in other compilers, as well as makes
|
||||
// sense.
|
||||
@ -770,9 +760,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
|
||||
return nullptr;
|
||||
|
||||
// If the 'if' clause is true, it makes the 'self' clause have no effect,
|
||||
// diagnose that here.
|
||||
// TODO OpenACC: When we add these two to other constructs, we might not
|
||||
// want to warn on this (for example, 'update').
|
||||
// diagnose that here. This only applies on compute/combined constructs.
|
||||
if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Update)
|
||||
return OpenACCSelfClause::Create(Ctx, Clause.getBeginLoc(),
|
||||
Clause.getLParenLoc(), Clause.getVarList(),
|
||||
Clause.getEndLoc());
|
||||
|
||||
const auto *Itr =
|
||||
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
|
||||
if (Itr != ExistingClauses.end()) {
|
||||
|
@ -11647,22 +11647,48 @@ template <typename Derived>
|
||||
void OpenACCClauseTransform<Derived>::VisitSelfClause(
|
||||
const OpenACCSelfClause &C) {
|
||||
|
||||
if (C.hasConditionExpr()) {
|
||||
Expr *Cond = const_cast<Expr *>(C.getConditionExpr());
|
||||
Sema::ConditionResult Res =
|
||||
Self.TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond,
|
||||
Sema::ConditionKind::Boolean);
|
||||
// If this is an 'update' 'self' clause, this is actually a var list instead.
|
||||
if (ParsedClause.getDirectiveKind() == OpenACCDirectiveKind::Update) {
|
||||
llvm::SmallVector<Expr *> InstantiatedVarList;
|
||||
for (Expr *CurVar : C.getVarList()) {
|
||||
ExprResult Res = Self.TransformExpr(CurVar);
|
||||
|
||||
if (Res.isInvalid() || !Res.get().second)
|
||||
return;
|
||||
if (!Res.isUsable())
|
||||
continue;
|
||||
|
||||
ParsedClause.setConditionDetails(Res.get().second);
|
||||
Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getClauseKind(),
|
||||
Res.get());
|
||||
|
||||
if (Res.isUsable())
|
||||
InstantiatedVarList.push_back(Res.get());
|
||||
}
|
||||
|
||||
ParsedClause.setVarListDetails(InstantiatedVarList,
|
||||
/*IsReadOnly=*/false, /*IsZero=*/false);
|
||||
|
||||
NewClause = OpenACCSelfClause::Create(
|
||||
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
|
||||
ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
|
||||
ParsedClause.getEndLoc());
|
||||
} else {
|
||||
|
||||
if (C.hasConditionExpr()) {
|
||||
Expr *Cond = const_cast<Expr *>(C.getConditionExpr());
|
||||
Sema::ConditionResult Res =
|
||||
Self.TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond,
|
||||
Sema::ConditionKind::Boolean);
|
||||
|
||||
if (Res.isInvalid() || !Res.get().second)
|
||||
return;
|
||||
|
||||
ParsedClause.setConditionDetails(Res.get().second);
|
||||
}
|
||||
|
||||
NewClause = OpenACCSelfClause::Create(
|
||||
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
|
||||
ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(),
|
||||
ParsedClause.getEndLoc());
|
||||
}
|
||||
|
||||
NewClause = OpenACCSelfClause::Create(
|
||||
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
|
||||
ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(),
|
||||
ParsedClause.getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
|
@ -12387,9 +12387,18 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
|
||||
}
|
||||
case OpenACCClauseKind::Self: {
|
||||
SourceLocation LParenLoc = readSourceLocation();
|
||||
Expr *CondExpr = readBool() ? readSubExpr() : nullptr;
|
||||
return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc,
|
||||
CondExpr, EndLoc);
|
||||
bool isConditionExprClause = readBool();
|
||||
if (isConditionExprClause) {
|
||||
Expr *CondExpr = readBool() ? readSubExpr() : nullptr;
|
||||
return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc,
|
||||
CondExpr, EndLoc);
|
||||
}
|
||||
unsigned NumVars = readInt();
|
||||
llvm::SmallVector<Expr *> VarList;
|
||||
for (unsigned I = 0; I < NumVars; ++I)
|
||||
VarList.push_back(readSubExpr());
|
||||
return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc, VarList,
|
||||
EndLoc);
|
||||
}
|
||||
case OpenACCClauseKind::NumGangs: {
|
||||
SourceLocation LParenLoc = readSourceLocation();
|
||||
|
@ -8321,9 +8321,16 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
|
||||
case OpenACCClauseKind::Self: {
|
||||
const auto *SC = cast<OpenACCSelfClause>(C);
|
||||
writeSourceLocation(SC->getLParenLoc());
|
||||
writeBool(SC->hasConditionExpr());
|
||||
if (SC->hasConditionExpr())
|
||||
AddStmt(const_cast<Expr*>(SC->getConditionExpr()));
|
||||
writeBool(SC->isConditionExprClause());
|
||||
if (SC->isConditionExprClause()) {
|
||||
writeBool(SC->hasConditionExpr());
|
||||
if (SC->hasConditionExpr())
|
||||
AddStmt(const_cast<Expr *>(SC->getConditionExpr()));
|
||||
} else {
|
||||
writeUInt32(SC->getVarList().size());
|
||||
for (Expr *E : SC->getVarList())
|
||||
AddStmt(E);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case OpenACCClauseKind::NumGangs: {
|
||||
|
@ -35,4 +35,7 @@ void uses(bool cond) {
|
||||
|
||||
// CHECK: #pragma acc update device_type(J) dtype(K)
|
||||
#pragma acc update device_type(J) dtype(K)
|
||||
|
||||
// CHECK: #pragma acc update self(I, iPtr, array, array[1], array[1:2])
|
||||
#pragma acc update self(I, iPtr, array, array[1], array[1:2])
|
||||
}
|
||||
|
@ -347,14 +347,12 @@ void SelfUpdate() {
|
||||
#pragma acc update self
|
||||
for(int i = 0; i < 5;++i) {}
|
||||
|
||||
// expected-error@+4{{use of undeclared identifier 'zero'}}
|
||||
// expected-error@+3{{expected ','}}
|
||||
// expected-error@+2{{expected expression}}
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
|
||||
// expected-error@+3{{use of undeclared identifier 'zero'}}
|
||||
// expected-error@+2{{expected ','}}
|
||||
// expected-error@+1{{expected expression}}
|
||||
#pragma acc update self(zero : s.array[s.value : 5], s.value), if_present
|
||||
for(int i = 0; i < 5;++i) {}
|
||||
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
|
||||
#pragma acc update self(s.array[s.value : 5], s.value), if_present
|
||||
for(int i = 0; i < 5;++i) {}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ void TemplFunc() {
|
||||
for (unsigned i = 0; i < 5; ++i);
|
||||
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: <<<NULL>>
|
||||
// CHECK-NEXT: ForStmt
|
||||
// CHECK: NullStmt
|
||||
|
||||
@ -65,6 +66,7 @@ void TemplFunc() {
|
||||
//
|
||||
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: <<<NULL>>
|
||||
// CHECK-NEXT: ForStmt
|
||||
// CHECK: NullStmt
|
||||
|
||||
|
@ -197,6 +197,7 @@ void TemplFunc() {
|
||||
while(true);
|
||||
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: <<<NULL>>
|
||||
// CHECK-NEXT: WhileStmt
|
||||
// CHECK-NEXT: CXXBoolLiteralExpr
|
||||
// CHECK-NEXT: NullStmt
|
||||
@ -393,6 +394,7 @@ void TemplFunc() {
|
||||
|
||||
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: <<<NULL>>
|
||||
// CHECK-NEXT: WhileStmt
|
||||
// CHECK-NEXT: CXXBoolLiteralExpr
|
||||
// CHECK-NEXT: NullStmt
|
||||
|
@ -10,6 +10,10 @@
|
||||
int some_int();
|
||||
long some_long();
|
||||
|
||||
int Global;
|
||||
short GlobalArray[5];
|
||||
|
||||
|
||||
void NormalFunc() {
|
||||
// CHECK-LABEL: NormalFunc
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
@ -70,6 +74,21 @@ void NormalFunc() {
|
||||
// CHECK-NEXT: CallExpr{{.*}}'long'
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()'
|
||||
|
||||
#pragma acc update self(Global, GlobalArray, GlobalArray[0], GlobalArray[0:1])
|
||||
// CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Global' 'int'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'GlobalArray' 'short[5]'
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}} 'short' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'GlobalArray' 'short[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 0
|
||||
// CHECK-NEXT: ArraySectionExpr
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'GlobalArray' 'short[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 0
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 1
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -124,6 +143,26 @@ void TemplFunc(T t) {
|
||||
// CHECK-NEXT: DependentScopeDeclRefExpr{{.*}}'<dependent type>'
|
||||
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'T'
|
||||
|
||||
decltype(T::value) Local = 0, LocalArray[5] = {};
|
||||
// CHECK-NEXT: DeclStmt
|
||||
// CHECK-NEXT: VarDecl
|
||||
// CHECK-NEXT: IntegerLiteral
|
||||
// CHECK-NEXT: VarDecl
|
||||
// CHECK-NEXT: InitListExpr
|
||||
|
||||
#pragma acc update self(Local, LocalArray, LocalArray[0], LocalArray[0:1])
|
||||
// CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'Local' 'decltype(T::value)'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(T::value)[5]'
|
||||
// CHECK-NEXT: ArraySubscriptExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(T::value)[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}}0
|
||||
// CHECK-NEXT: ArraySectionExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(T::value)[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}}0
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}}1
|
||||
|
||||
// Instantiation:
|
||||
// CHECK-NEXT: FunctionDecl{{.*}} TemplFunc 'void (SomeStruct)' implicit_instantiation
|
||||
// CHECK-NEXT: TemplateArgument type 'SomeStruct'
|
||||
@ -194,6 +233,27 @@ void TemplFunc(T t) {
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int'
|
||||
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'SomeStruct'
|
||||
|
||||
// CHECK-NEXT: DeclStmt
|
||||
// CHECK-NEXT: VarDecl
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: IntegerLiteral
|
||||
// CHECK-NEXT: VarDecl
|
||||
// CHECK-NEXT: InitListExpr
|
||||
// CHECK-NEXT: array_filler
|
||||
|
||||
// CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
|
||||
// CHECK-NEXT: self clause
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'Local' 'decltype(SomeStruct::value)':'const unsigned int'
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(SomeStruct::value)[5]'
|
||||
// CHECK-NEXT: ArraySubscriptExpr
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(SomeStruct::value)[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}}0
|
||||
// CHECK-NEXT: ArraySectionExpr
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(SomeStruct::value)[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}}1
|
||||
}
|
||||
|
||||
struct SomeStruct{
|
||||
|
@ -4,28 +4,20 @@ struct NotConvertible{} NC;
|
||||
int getI();
|
||||
void uses() {
|
||||
int Var;
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update async self(Var)
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update wait self(Var)
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update self(Var) device_type(I)
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update if(true) self(Var)
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update if_present self(Var)
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update self(Var)
|
||||
// expected-warning@+1{{OpenACC clause 'host' not yet implemented}}
|
||||
#pragma acc update host(Var)
|
||||
// expected-warning@+1{{OpenACC clause 'device' not yet implemented}}
|
||||
#pragma acc update device(Var)
|
||||
|
||||
// expected-warning@+3{{OpenACC clause 'self' not yet implemented}}
|
||||
// expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a 'update' construct}}
|
||||
// expected-note@+1{{previous clause is here}}
|
||||
#pragma acc update self(Var) device_type(I) if(true)
|
||||
// expected-warning@+3{{OpenACC clause 'self' not yet implemented}}
|
||||
// expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a 'update' construct}}
|
||||
// expected-note@+1{{previous clause is here}}
|
||||
#pragma acc update self(Var) device_type(I) if_present
|
||||
@ -39,12 +31,9 @@ void uses() {
|
||||
// expected-note@+1{{previous clause is here}}
|
||||
#pragma acc update device_type(I) device(Var)
|
||||
// These 2 are OK.
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update self(Var) device_type(I) async
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update self(Var) device_type(I) wait
|
||||
// Unless otherwise specified, we assume 'device_type' can happen after itself.
|
||||
// expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
|
||||
#pragma acc update self(Var) device_type(I) device_type(I)
|
||||
|
||||
// TODO: OpenACC: These should diagnose because there isn't at least 1 of
|
||||
@ -128,3 +117,51 @@ void uses() {
|
||||
// expected-error@+1{{OpenACC clause 'wait' requires expression of integer type ('struct NotConvertible' invalid)}}
|
||||
#pragma acc update wait(devnum:arr : queues: arr, NC, 5)
|
||||
}
|
||||
|
||||
struct SomeS {
|
||||
int Array[5];
|
||||
int MemberOfComp;
|
||||
};
|
||||
|
||||
template<typename I, typename T>
|
||||
void varlist_restrictions_templ() {
|
||||
I iArray[5];
|
||||
T Single;
|
||||
T Array[5];
|
||||
|
||||
// Members of a subarray of struct or class type may not appear, but others
|
||||
// are permitted to.
|
||||
#pragma acc update self(iArray[0:1])
|
||||
|
||||
#pragma acc update self(Array[0:1])
|
||||
|
||||
// expected-error@+1{{OpenACC sub-array is not allowed here}}
|
||||
#pragma acc update self(Array[0:1].MemberOfComp)
|
||||
}
|
||||
|
||||
void varlist_restrictions() {
|
||||
varlist_restrictions_templ<int, SomeS>();// expected-note{{in instantiation of}}
|
||||
int iArray[5];
|
||||
SomeS Single;
|
||||
SomeS Array[5];
|
||||
|
||||
int LocalInt;
|
||||
int *LocalPtr;
|
||||
|
||||
#pragma acc update self(LocalInt, LocalPtr, Single)
|
||||
|
||||
#pragma acc update self(Single.MemberOfComp)
|
||||
|
||||
#pragma acc update self(Single.Array[0:1])
|
||||
|
||||
|
||||
// Members of a subarray of struct or class type may not appear, but others
|
||||
// are permitted to.
|
||||
#pragma acc update self(iArray[0:1])
|
||||
|
||||
#pragma acc update self(Array[0:1])
|
||||
|
||||
// expected-error@+1{{OpenACC sub-array is not allowed here}}
|
||||
#pragma acc update self(Array[0:1].MemberOfComp)
|
||||
}
|
||||
|
||||
|
@ -2839,8 +2839,13 @@ void OpenACCClauseEnqueue::VisitIfClause(const OpenACCIfClause &C) {
|
||||
Visitor.AddStmt(C.getConditionExpr());
|
||||
}
|
||||
void OpenACCClauseEnqueue::VisitSelfClause(const OpenACCSelfClause &C) {
|
||||
if (C.hasConditionExpr())
|
||||
Visitor.AddStmt(C.getConditionExpr());
|
||||
if (C.isConditionExprClause()) {
|
||||
if (C.hasConditionExpr())
|
||||
Visitor.AddStmt(C.getConditionExpr());
|
||||
} else {
|
||||
for (Expr *Var : C.getVarList())
|
||||
Visitor.AddStmt(Var);
|
||||
}
|
||||
}
|
||||
void OpenACCClauseEnqueue::VisitNumWorkersClause(
|
||||
const OpenACCNumWorkersClause &C) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user