[OPENMP50]Add parsing/sema analysis for nontemporal clause.
Add basic support for parsing/sema analysis of the nontemporal clause in
simd-based directives.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index afe0f1a..915bf53 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -83,7 +83,7 @@
DeclRefExpr *PrivateCopy = nullptr;
};
using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
- using AlignedMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
+ using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
using LCDeclInfo = std::pair<unsigned, VarDecl *>;
using LoopControlVariablesMapTy =
llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
@@ -125,7 +125,8 @@
struct SharingMapTy {
DeclSAMapTy SharingMap;
DeclReductionMapTy ReductionMap;
- AlignedMapTy AlignedMap;
+ UsedRefMapTy AlignedMap;
+ UsedRefMapTy NontemporalMap;
MappedExprComponentsTy MappedExprComponents;
LoopControlVariablesMapTy LCVMap;
DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
@@ -421,6 +422,10 @@
/// add it and return NULL; otherwise return previous occurrence's expression
/// for diagnostics.
const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
+ /// If 'nontemporal' declaration for given variable \a D was not seen yet,
+ /// add it and return NULL; otherwise return previous occurrence's expression
+ /// for diagnostics.
+ const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
/// Register specified variable as loop control variable.
void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
@@ -1073,6 +1078,21 @@
return It->second;
}
+const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
+ const Expr *NewDE) {
+ assert(!isStackEmpty() && "Data sharing attributes stack is empty");
+ D = getCanonicalDecl(D);
+ SharingMapTy &StackElem = getTopOfStack();
+ auto It = StackElem.NontemporalMap.find(D);
+ if (It == StackElem.NontemporalMap.end()) {
+ assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
+ StackElem.NontemporalMap[D] = NewDE;
+ return nullptr;
+ }
+ assert(It->second && "Unexpected nullptr expr in the aligned map");
+ return It->second;
+}
+
void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
@@ -4874,6 +4894,7 @@
case OMPC_from:
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
+ case OMPC_nontemporal:
continue;
case OMPC_allocator:
case OMPC_flush:
@@ -5019,8 +5040,9 @@
// OpenMP [2.8.1, simd construct, Restrictions]
// A list-item cannot appear in more than one aligned clause.
if (AlignedArgs.count(CanonPVD) > 0) {
- Diag(E->getExprLoc(), diag::err_omp_aligned_twice)
- << 1 << E->getSourceRange();
+ Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
+ << 1 << getOpenMPClauseName(OMPC_aligned)
+ << E->getSourceRange();
Diag(AlignedArgs[CanonPVD]->getExprLoc(),
diag::note_omp_explicit_dsa)
<< getOpenMPClauseName(OMPC_aligned);
@@ -5042,8 +5064,8 @@
}
if (isa<CXXThisExpr>(E)) {
if (AlignedThis) {
- Diag(E->getExprLoc(), diag::err_omp_aligned_twice)
- << 2 << E->getSourceRange();
+ Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
+ << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
<< getOpenMPClauseName(OMPC_aligned);
}
@@ -10735,6 +10757,7 @@
case OMPC_atomic_default_mem_order:
case OMPC_device_type:
case OMPC_match:
+ case OMPC_nontemporal:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -11445,6 +11468,7 @@
case OMPC_atomic_default_mem_order:
case OMPC_device_type:
case OMPC_match:
+ case OMPC_nontemporal:
llvm_unreachable("Unexpected OpenMP clause.");
}
return CaptureRegion;
@@ -11868,6 +11892,7 @@
case OMPC_dynamic_allocators:
case OMPC_device_type:
case OMPC_match:
+ case OMPC_nontemporal:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -12048,6 +12073,7 @@
case OMPC_atomic_default_mem_order:
case OMPC_device_type:
case OMPC_match:
+ case OMPC_nontemporal:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -12259,6 +12285,7 @@
case OMPC_atomic_default_mem_order:
case OMPC_device_type:
case OMPC_match:
+ case OMPC_nontemporal:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -12426,6 +12453,9 @@
Res = ActOnOpenMPAllocateClause(TailExpr, VarList, StartLoc, LParenLoc,
ColonLoc, EndLoc);
break;
+ case OMPC_nontemporal:
+ Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -14553,7 +14583,8 @@
// OpenMP [2.8.1, simd construct, Restrictions]
// A list-item cannot appear in more than one aligned clause.
if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
- Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange;
+ Diag(ELoc, diag::err_omp_used_in_clause_twice)
+ << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
<< getOpenMPClauseName(OMPC_aligned);
continue;
@@ -17122,3 +17153,49 @@
return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator,
ColonLoc, EndLoc, Vars);
}
+
+OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (Expr *RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
+ SourceLocation ELoc;
+ SourceRange ERange;
+ Expr *SimpleRefExpr = RefExpr;
+ auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
+ if (Res.second)
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ ValueDecl *D = Res.first;
+ if (!D)
+ continue;
+
+ auto *VD = dyn_cast<VarDecl>(D);
+
+ // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
+ // A list-item cannot appear in more than one nontemporal clause.
+ if (const Expr *PrevRef =
+ DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
+ Diag(ELoc, diag::err_omp_used_in_clause_twice)
+ << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
+ Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
+ << getOpenMPClauseName(OMPC_nontemporal);
+ continue;
+ }
+
+ DeclRefExpr *Ref = nullptr;
+ if (!VD && isOpenMPCapturedDecl(D) && !CurContext->isDependentContext())
+ Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
+ Vars.push_back((VD || !Ref || CurContext->isDependentContext())
+ ? RefExpr->IgnoreParens()
+ : Ref);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ Vars);
+}