[OPENMP50]Codegen for nontemporal clause.
Summary:
Basic codegen for the declarations marked as nontemporal. Also, if the
base declaration in the member expression is marked as nontemporal,
lvalue for member decl access inherits nonteporal flag from the base
lvalue.
Reviewers: rjmccall, hfinkel, jdoerfert
Subscribers: guansong, arphaman, caomhin, kkwli0, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D71708
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index cd42fae..c729037 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2566,21 +2566,35 @@
VD = VD->getCanonicalDecl();
if (auto *FD = LambdaCaptureFields.lookup(VD))
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
- else if (CapturedStmtInfo) {
+ if (CapturedStmtInfo) {
auto I = LocalDeclMap.find(VD);
if (I != LocalDeclMap.end()) {
+ LValue CapLVal;
if (VD->getType()->isReferenceType())
- return EmitLoadOfReferenceLValue(I->second, VD->getType(),
- AlignmentSource::Decl);
- return MakeAddrLValue(I->second, T);
+ CapLVal = EmitLoadOfReferenceLValue(I->second, VD->getType(),
+ AlignmentSource::Decl);
+ else
+ CapLVal = MakeAddrLValue(I->second, T);
+ // Mark lvalue as nontemporal if the variable is marked as nontemporal
+ // in simd context.
+ if (getLangOpts().OpenMP &&
+ CGM.getOpenMPRuntime().isNontemporalDecl(VD))
+ CapLVal.setNontemporal(/*Value=*/true);
+ return CapLVal;
}
LValue CapLVal =
EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
CapturedStmtInfo->getContextValue());
- return MakeAddrLValue(
+ CapLVal = MakeAddrLValue(
Address(CapLVal.getPointer(*this), getContext().getDeclAlign(VD)),
CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl),
CapLVal.getTBAAInfo());
+ // Mark lvalue as nontemporal if the variable is marked as nontemporal
+ // in simd context.
+ if (getLangOpts().OpenMP &&
+ CGM.getOpenMPRuntime().isNontemporalDecl(VD))
+ CapLVal.setNontemporal(/*Value=*/true);
+ return CapLVal;
}
assert(isa<BlockDecl>(CurCodeDecl));
@@ -3929,6 +3943,15 @@
if (auto *Field = dyn_cast<FieldDecl>(ND)) {
LValue LV = EmitLValueForField(BaseLV, Field);
setObjCGCLValueClass(getContext(), E, LV);
+ if (getLangOpts().OpenMP) {
+ // If the member was explicitly marked as nontemporal, mark it as
+ // nontemporal. If the base lvalue is marked as nontemporal, mark access
+ // to children as nontemporal too.
+ if ((IsWrappedCXXThis(BaseExpr) &&
+ CGM.getOpenMPRuntime().isNontemporalDecl(Field)) ||
+ BaseLV.isNontemporal())
+ LV.setNontemporal(/*Value=*/true);
+ }
return LV;
}
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 1aae18b..2a53e99 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -17,6 +17,7 @@
#include "CodeGenFunction.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Basic/BitmaskEnum.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
@@ -11341,6 +11342,46 @@
return true;
}
+CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
+ CodeGenModule &CGM, const OMPLoopDirective &S)
+ : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
+ assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
+ if (!NeedToPush)
+ return;
+ NontemporalDeclsSet &DS =
+ CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
+ for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
+ for (const Stmt *Ref : C->private_refs()) {
+ const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
+ const ValueDecl *VD;
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
+ VD = DRE->getDecl();
+ } else {
+ const auto *ME = cast<MemberExpr>(SimpleRefExpr);
+ assert((ME->isImplicitCXXThis() ||
+ isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&
+ "Expected member of current class.");
+ VD = ME->getMemberDecl();
+ }
+ DS.insert(VD);
+ }
+ }
+}
+
+CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
+ if (!NeedToPush)
+ return;
+ CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
+}
+
+bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
+ assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
+
+ return llvm::any_of(
+ CGM.getOpenMPRuntime().NontemporalDeclsStack,
+ [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
+}
+
llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index d806c27..f158245 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -211,6 +211,16 @@
~DisableAutoDeclareTargetRAII();
};
+ /// Manages list of nontemporal decls for the specified directive.
+ class NontemporalDeclsRAII {
+ CodeGenModule &CGM;
+ const bool NeedToPush;
+
+ public:
+ NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S);
+ ~NontemporalDeclsRAII();
+ };
+
protected:
CodeGenModule &CGM;
StringRef FirstSeparator, Separator;
@@ -650,6 +660,11 @@
std::pair<GlobalDecl, GlobalDecl>>
DeferredVariantFunction;
+ using NontemporalDeclsSet = llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>>;
+ /// Stack for list of declarations in current context marked as nontemporal.
+ /// The set is the union of all current stack elements.
+ llvm::SmallVector<NontemporalDeclsSet, 4> NontemporalDeclsStack;
+
/// Flag for keeping track of weather a requires unified_shared_memory
/// directive is present.
bool HasRequiresUnifiedSharedMemory = false;
@@ -1663,6 +1678,10 @@
/// Emits the definition of the declare variant function.
virtual bool emitDeclareVariant(GlobalDecl GD, bool IsForDefinition);
+
+ /// Checks if the \p VD variable is marked as nontemporal declaration in
+ /// current context.
+ bool isNontemporalDecl(const ValueDecl *VD) const;
};
/// Class supports emissionof SIMD-only code.
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index e8a3790..a2a59b6 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1803,8 +1803,9 @@
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S,
const RegionCodeGenTy &SimdInitGen,
const RegionCodeGenTy &BodyCodeGen) {
- auto &&ThenGen = [&SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S);
CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
SimdInitGen(CGF);