summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp33
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp41
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.h19
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp5
4 files changed, 91 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index cd42faefab0..c729037852e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2566,21 +2566,35 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
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 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
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 1aae18b4504..2a53e999353 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 @@ bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
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 d806c27fdcb..f1582457ed2 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -211,6 +211,16 @@ public:
~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 @@ private:
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 @@ public:
/// 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 e8a3790e3b5..a2a59b64ddb 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1803,8 +1803,9 @@ static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
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);
OpenPOWER on IntegriCloud