diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 55 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 319 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 6 |
7 files changed, 218 insertions, 194 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index d0b1de81006..87e2ed61af2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -4709,7 +4709,8 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); - OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); + OutlinedFn = + CGF.GenerateOpenMPCapturedStmtFunction(CS, /*CastValToPtr=*/true); // If this target outline function is not an offload entry, we don't need to // register it. @@ -5553,8 +5554,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_BYCOPY); if (!RI->getType()->isAnyPointerType()) { // If the field is not a pointer, we need to save the actual value - // and - // load it as a void pointer. + // and load it as a void pointer. auto DstAddr = CGF.CreateMemTemp( Ctx.getUIntPtrType(), Twine(CI->getCapturedVar()->getName()) + ".casted"); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 5cf0cae161b..d28f2cceb08 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -172,7 +172,8 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType, } llvm::Function * -CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { +CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, + bool CastValToPtr) { assert( CapturedStmtInfo && "CapturedStmtInfo should be set when generating the captured function"); @@ -196,9 +197,11 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { // uintptr. This is necessary given that the runtime library is only able to // deal with pointers. We can pass in the same way the VLA type sizes to the // outlined function. - if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) || - I->capturesVariableArrayType()) - ArgType = Ctx.getUIntPtrType(); + if (CastValToPtr) { + if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) || + I->capturesVariableArrayType()) + ArgType = Ctx.getUIntPtrType(); + } if (I->capturesVariable() || I->capturesVariableByCopy()) { CapVar = I->getCapturedVar(); @@ -252,9 +255,12 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { AlignmentSource::Decl); if (FD->hasCapturedVLAType()) { LValue CastedArgLVal = - MakeAddrLValue(castValueFromUintptr(*this, FD->getType(), - Args[Cnt]->getName(), ArgLVal), - FD->getType(), AlignmentSource::Decl); + CastValToPtr + ? MakeAddrLValue(castValueFromUintptr(*this, FD->getType(), + Args[Cnt]->getName(), + ArgLVal), + FD->getType(), AlignmentSource::Decl) + : ArgLVal; auto *ExprArg = EmitLoadOfLValue(CastedArgLVal, SourceLocation()).getScalarVal(); auto VAT = FD->getCapturedVLAType(); @@ -274,10 +280,16 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { "Not expecting a captured pointer."); auto *Var = I->getCapturedVar(); QualType VarTy = Var->getType(); - setAddrOfLocalVar(I->getCapturedVar(), - castValueFromUintptr(*this, FD->getType(), - Args[Cnt]->getName(), ArgLVal, - VarTy->isReferenceType())); + if (!CastValToPtr && VarTy->isReferenceType()) { + Address Temp = CreateMemTemp(VarTy); + Builder.CreateStore(ArgLVal.getPointer(), Temp); + ArgLVal = MakeAddrLValue(Temp, VarTy); + } + setAddrOfLocalVar(Var, CastValToPtr ? castValueFromUintptr( + *this, FD->getType(), + Args[Cnt]->getName(), ArgLVal, + VarTy->isReferenceType()) + : ArgLVal.getAddress()); } else { // If 'this' is captured, load it into CXXThisValue. assert(I->capturesThis()); @@ -564,18 +576,25 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, auto InitsRef = C->inits().begin(); for (auto IInit : C->private_copies()) { auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); + bool ThisFirstprivateIsLastprivate = + Lastprivates.count(OrigVD->getCanonicalDecl()) > 0; + auto *FD = CapturedStmtInfo->lookup(OrigVD); + if (!ThisFirstprivateIsLastprivate && FD && + !FD->getType()->isReferenceType()) { + EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()); + ++IRef; + ++InitsRef; + continue; + } FirstprivateIsLastprivate = - FirstprivateIsLastprivate || - (Lastprivates.count(OrigVD->getCanonicalDecl()) > 0); + FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate; if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) { auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl()); bool IsRegistered; - DeclRefExpr DRE( - const_cast<VarDecl *>(OrigVD), - /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup( - OrigVD) != nullptr, - (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); + DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), + /*RefersToEnclosingVariableOrCapture=*/FD != nullptr, + (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); Address OriginalAddr = EmitLValue(&DRE).getAddress(); QualType Type = VD->getType(); if (Type->isArrayType()) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3a3e54ce620..0100ac3ecda 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -191,6 +191,8 @@ public: CXXThisFieldDecl = *Field; else if (I->capturesVariable()) CaptureFields[I->getCapturedVar()] = *Field; + else if (I->capturesVariableByCopy()) + CaptureFields[I->getCapturedVar()] = *Field; } } @@ -2229,8 +2231,7 @@ public: llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S); Address GenerateCapturedStmtArgument(const CapturedStmt &S); llvm::Function *GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, - QualType ReturnQTy); - llvm::Function *GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S); + bool CastValToPtr = false); void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars); void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 35e303ee923..b4692fca229 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1492,7 +1492,8 @@ IdentifierInfo *Sema::getFloat128Identifier() const { void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD, CapturedRegionKind K) { CapturingScopeInfo *CSI = new CapturedRegionScopeInfo( - getDiagnostics(), S, CD, RD, CD->getContextParam(), K); + getDiagnostics(), S, CD, RD, CD->getContextParam(), K, + (getLangOpts().OpenMP && K == CR_OpenMP) ? getOpenMPNestingLevel() : 0); CSI->ReturnType = Context.VoidTy; FunctionScopes.push_back(CSI); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 68fd92fbe1a..29be09e8fea 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13281,7 +13281,8 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, return false; } const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>(); - if (HasBlocksAttr || CaptureType->isReferenceType()) { + if (HasBlocksAttr || CaptureType->isReferenceType() || + (S.getLangOpts().OpenMP && S.IsOpenMPCapturedDecl(Var))) { // Block capture by reference does not change the capture or // declaration reference types. ByRef = true; @@ -13349,14 +13350,13 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, QualType &DeclRefType, const bool RefersToCapturedVariable, Sema &S) { - // By default, capture variables by reference. bool ByRef = true; // Using an LValue reference type is consistent with Lambdas (see below). - if (S.getLangOpts().OpenMP) { - ByRef = S.IsOpenMPCapturedByRef(Var, RSI); + if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) { if (S.IsOpenMPCapturedDecl(Var)) DeclRefType = DeclRefType.getUnqualifiedType(); + ByRef = S.IsOpenMPCapturedByRef(Var, RSI->OpenMPLevel); } if (ByRef) @@ -13562,7 +13562,6 @@ bool Sema::tryCaptureVariable( bool Nested = false; bool Explicit = (Kind != TryCapture_Implicit); unsigned FunctionScopesIndex = MaxFunctionScopesIndex; - unsigned OpenMPLevel = 0; do { // Only block literals, captured statements, and lambda expressions can // capture; other scopes don't work. @@ -13628,20 +13627,19 @@ bool Sema::tryCaptureVariable( // just break here. Similarly, global variables that are captured in a // target region should not be captured outside the scope of the region. if (RSI->CapRegionKind == CR_OpenMP) { - auto isTargetCap = isOpenMPTargetCapturedDecl(Var, OpenMPLevel); + auto IsTargetCap = isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel); // When we detect target captures we are looking from inside the // target region, therefore we need to propagate the capture from the // enclosing region. Therefore, the capture is not initially nested. - if (isTargetCap) + if (IsTargetCap) FunctionScopesIndex--; - if (isTargetCap || isOpenMPPrivateDecl(Var, OpenMPLevel)) { - Nested = !isTargetCap; + if (IsTargetCap || isOpenMPPrivateDecl(Var, RSI->OpenMPLevel)) { + Nested = !IsTargetCap; DeclRefType = DeclRefType.getUnqualifiedType(); CaptureType = Context.getLValueReferenceType(DeclRefType); break; } - ++OpenMPLevel; } } } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index ea26f6a4f16..f249e3f1e07 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -45,46 +45,26 @@ enum DefaultDataSharingAttributes { DSA_shared = 1 << 1 /// \brief Default data sharing attribute 'shared'. }; -template <class T> struct MatchesAny { - explicit MatchesAny(ArrayRef<T> Arr) : Arr(std::move(Arr)) {} - bool operator()(T Kind) { - for (auto KindEl : Arr) - if (KindEl == Kind) - return true; - return false; - } - -private: - ArrayRef<T> Arr; -}; -struct MatchesAlways { - MatchesAlways() {} - template <class T> bool operator()(T) { return true; } -}; - -typedef MatchesAny<OpenMPClauseKind> MatchesAnyClause; -typedef MatchesAny<OpenMPDirectiveKind> MatchesAnyDirective; - /// \brief Stack for tracking declarations used in OpenMP directives and /// clauses and their data-sharing attributes. -class DSAStackTy { +class DSAStackTy final { public: - struct DSAVarData { - OpenMPDirectiveKind DKind; - OpenMPClauseKind CKind; - Expr *RefExpr; - DeclRefExpr *PrivateCopy; + struct DSAVarData final { + OpenMPDirectiveKind DKind = OMPD_unknown; + OpenMPClauseKind CKind = OMPC_unknown; + Expr *RefExpr = nullptr; + DeclRefExpr *PrivateCopy = nullptr; SourceLocation ImplicitDSALoc; - DSAVarData() - : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr), - PrivateCopy(nullptr), ImplicitDSALoc() {} + DSAVarData() {} }; private: - struct DSAInfo { - OpenMPClauseKind Attributes; - Expr *RefExpr; - DeclRefExpr *PrivateCopy; + struct DSAInfo final { + OpenMPClauseKind Attributes = OMPC_unknown; + /// Pointer to a reference expression and a flag which shows that the + /// variable is marked as lastprivate(true) or not (false). + llvm::PointerIntPair<Expr *, 1, bool> RefExpr; + DeclRefExpr *PrivateCopy = nullptr; }; typedef llvm::DenseMap<ValueDecl *, DSAInfo> DeclSAMapTy; typedef llvm::DenseMap<ValueDecl *, Expr *> AlignedMapTy; @@ -96,36 +76,30 @@ private: typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>> CriticalsWithHintsTy; - struct SharingMapTy { + struct SharingMapTy final { DeclSAMapTy SharingMap; AlignedMapTy AlignedMap; MappedExprComponentsTy MappedExprComponents; LoopControlVariablesMapTy LCVMap; - DefaultDataSharingAttributes DefaultAttr; + DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; SourceLocation DefaultAttrLoc; - OpenMPDirectiveKind Directive; + OpenMPDirectiveKind Directive = OMPD_unknown; DeclarationNameInfo DirectiveName; - Scope *CurScope; + Scope *CurScope = nullptr; SourceLocation ConstructLoc; /// \brief first argument (Expr *) contains optional argument of the /// 'ordered' clause, the second one is true if the regions has 'ordered' /// clause, false otherwise. llvm::PointerIntPair<Expr *, 1, bool> OrderedRegion; - bool NowaitRegion; - bool CancelRegion; - unsigned AssociatedLoops; + bool NowaitRegion = false; + bool CancelRegion = false; + unsigned AssociatedLoops = 1; SourceLocation InnerTeamsRegionLoc; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) - : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified), - Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope), - ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false), - CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {} - SharingMapTy() - : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified), - Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr), - ConstructLoc(), OrderedRegion(), NowaitRegion(false), - CancelRegion(false), AssociatedLoops(1), InnerTeamsRegionLoc() {} + : Directive(DKind), DirectiveName(Name), CurScope(CurScope), + ConstructLoc(Loc) {} + SharingMapTy() {} }; typedef SmallVector<SharingMapTy, 4> StackTy; @@ -134,9 +108,9 @@ private: StackTy Stack; /// \brief true, if check for DSA must be from parent directive, false, if /// from current directive. - OpenMPClauseKind ClauseKindMode; + OpenMPClauseKind ClauseKindMode = OMPC_unknown; Sema &SemaRef; - bool ForceCapturing; + bool ForceCapturing = false; CriticalsWithHintsTy Criticals; typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator; @@ -147,9 +121,7 @@ private: bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter); public: - explicit DSAStackTy(Sema &S) - : Stack(1), ClauseKindMode(OMPC_unknown), SemaRef(S), - ForceCapturing(false) {} + explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {} bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; } void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; } @@ -211,21 +183,24 @@ public: /// \brief Checks if the specified variables has data-sharing attributes which /// match specified \a CPred predicate in any directive which matches \a DPred /// predicate. - template <class ClausesPredicate, class DirectivesPredicate> - DSAVarData hasDSA(ValueDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred, bool FromParent); + DSAVarData hasDSA(ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, + bool FromParent); /// \brief Checks if the specified variables has data-sharing attributes which /// match specified \a CPred predicate in any innermost directive which /// matches \a DPred predicate. - template <class ClausesPredicate, class DirectivesPredicate> - DSAVarData hasInnermostDSA(ValueDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred, bool FromParent); + DSAVarData + hasInnermostDSA(ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, + bool FromParent); /// \brief Checks if the specified variables has explicit data-sharing /// attributes which match specified \a CPred predicate at the specified /// OpenMP region. bool hasExplicitDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, - unsigned Level); + unsigned Level, bool NotLastprivate = false); /// \brief Returns true if the directive at level \Level matches in the /// specified \a DPred predicate. @@ -234,8 +209,10 @@ public: unsigned Level); /// \brief Finds a directive which matches specified \a DPred predicate. - template <class NamedDirectivesPredicate> - bool hasDirective(NamedDirectivesPredicate DPred, bool FromParent); + bool hasDirective(const llvm::function_ref<bool(OpenMPDirectiveKind, + const DeclarationNameInfo &, + SourceLocation)> &DPred, + bool FromParent); /// \brief Returns currently analyzed directive. OpenMPDirectiveKind getCurrentDirective() const { @@ -247,8 +224,6 @@ public: return Stack[Stack.size() - 2].Directive; return OMPD_unknown; } - /// \brief Return the directive associated with the provided scope. - OpenMPDirectiveKind getDirectiveForScope(const Scope *S) const; /// \brief Set default data sharing attribute to none. void setDefaultDSANone(SourceLocation Loc) { @@ -380,6 +355,11 @@ public: MEC.resize(MEC.size() + 1); MEC.back().append(Components.begin(), Components.end()); } + + unsigned getNestingLevel() const { + assert(Stack.size() > 1); + return Stack.size() - 2; + } }; bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { return isOpenMPParallelDirective(DKind) || isOpenMPTaskingDirective(DKind) || @@ -444,7 +424,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator& Iter, // Explicitly specified attributes and local variables with predetermined // attributes. if (Iter->SharingMap.count(D)) { - DVar.RefExpr = Iter->SharingMap[D].RefExpr; + DVar.RefExpr = Iter->SharingMap[D].RefExpr.getPointer(); DVar.PrivateCopy = Iter->SharingMap[D].PrivateCopy; DVar.CKind = Iter->SharingMap[D].Attributes; DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; @@ -562,16 +542,32 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A, DeclRefExpr *PrivateCopy) { D = getCanonicalDecl(D); if (A == OMPC_threadprivate) { - Stack[0].SharingMap[D].Attributes = A; - Stack[0].SharingMap[D].RefExpr = E; - Stack[0].SharingMap[D].PrivateCopy = nullptr; + auto &Data = Stack[0].SharingMap[D]; + Data.Attributes = A; + Data.RefExpr.setPointer(E); + Data.PrivateCopy = nullptr; } else { assert(Stack.size() > 1 && "Data-sharing attributes stack is empty"); - Stack.back().SharingMap[D].Attributes = A; - Stack.back().SharingMap[D].RefExpr = E; - Stack.back().SharingMap[D].PrivateCopy = PrivateCopy; - if (PrivateCopy) - addDSA(PrivateCopy->getDecl(), PrivateCopy, A); + auto &Data = Stack.back().SharingMap[D]; + assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || + (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || + (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || + (isLoopControlVariable(D).first && A == OMPC_private)); + if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) { + Data.RefExpr.setInt(/*IntVal=*/true); + return; + } + const bool IsLastprivate = + A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate; + Data.Attributes = A; + Data.RefExpr.setPointerAndInt(E, IsLastprivate); + Data.PrivateCopy = PrivateCopy; + if (PrivateCopy) { + auto &Data = Stack.back().SharingMap[PrivateCopy->getDecl()]; + Data.Attributes = A; + Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); + Data.PrivateCopy = nullptr; + } } } @@ -641,7 +637,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { OMPC_threadprivate); } if (Stack[0].SharingMap.count(D)) { - DVar.RefExpr = Stack[0].SharingMap[D].RefExpr; + DVar.RefExpr = Stack[0].SharingMap[D].RefExpr.getPointer(); DVar.CKind = OMPC_threadprivate; return DVar; } @@ -658,9 +654,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { // in a Construct, C/C++, predetermined, p.7] // Variables with static storage duration that are declared in a scope // inside the construct are shared. + auto &&MatchesAlways = [](OpenMPDirectiveKind) -> bool { return true; }; if (VD && VD->isStaticDataMember()) { - DSAVarData DVarTemp = - hasDSA(D, isOpenMPPrivate, MatchesAlways(), FromParent); + DSAVarData DVarTemp = hasDSA(D, isOpenMPPrivate, MatchesAlways, FromParent); if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr) return DVar; @@ -685,8 +681,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { RD->hasMutableFields())) { // Variables with const-qualified type having no mutable member may be // listed in a firstprivate clause, even if they are static data members. - DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate), - MatchesAlways(), FromParent); + DSAVarData DVarTemp = hasDSA( + D, [](OpenMPClauseKind C) -> bool { return C == OMPC_firstprivate; }, + MatchesAlways, FromParent); if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) return DVar; @@ -703,7 +700,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) { } auto I = std::prev(StartI); if (I->SharingMap.count(D)) { - DVar.RefExpr = I->SharingMap[D].RefExpr; + DVar.RefExpr = I->SharingMap[D].RefExpr.getPointer(); DVar.PrivateCopy = I->SharingMap[D].PrivateCopy; DVar.CKind = I->SharingMap[D].Attributes; DVar.ImplicitDSALoc = I->DefaultAttrLoc; @@ -723,10 +720,11 @@ DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, return getDSA(StartI, D); } -template <class ClausesPredicate, class DirectivesPredicate> -DSAStackTy::DSAVarData DSAStackTy::hasDSA(ValueDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred, - bool FromParent) { +DSAStackTy::DSAVarData +DSAStackTy::hasDSA(ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, + bool FromParent) { D = getCanonicalDecl(D); auto StartI = std::next(Stack.rbegin()); auto EndI = Stack.rend(); @@ -743,10 +741,10 @@ DSAStackTy::DSAVarData DSAStackTy::hasDSA(ValueDecl *D, ClausesPredicate CPred, return DSAVarData(); } -template <class ClausesPredicate, class DirectivesPredicate> -DSAStackTy::DSAVarData -DSAStackTy::hasInnermostDSA(ValueDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred, bool FromParent) { +DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( + ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, + const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, + bool FromParent) { D = getCanonicalDecl(D); auto StartI = std::next(Stack.rbegin()); auto EndI = Stack.rend(); @@ -766,36 +764,37 @@ DSAStackTy::hasInnermostDSA(ValueDecl *D, ClausesPredicate CPred, bool DSAStackTy::hasExplicitDSA( ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> &CPred, - unsigned Level) { + unsigned Level, bool NotLastprivate) { if (CPred(ClauseKindMode)) return true; - if (isClauseParsingMode()) - ++Level; D = getCanonicalDecl(D); - auto StartI = Stack.rbegin(); - auto EndI = std::prev(Stack.rend()); + auto StartI = std::next(Stack.begin()); + auto EndI = Stack.end(); if (std::distance(StartI, EndI) <= (int)Level) return false; std::advance(StartI, Level); - return (StartI->SharingMap.count(D) > 0) && StartI->SharingMap[D].RefExpr && - CPred(StartI->SharingMap[D].Attributes); + return (StartI->SharingMap.count(D) > 0) && + StartI->SharingMap[D].RefExpr.getPointer() && + CPred(StartI->SharingMap[D].Attributes) && + (!NotLastprivate || !StartI->SharingMap[D].RefExpr.getInt()); } bool DSAStackTy::hasExplicitDirective( const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred, unsigned Level) { - if (isClauseParsingMode()) - ++Level; - auto StartI = Stack.rbegin(); - auto EndI = std::prev(Stack.rend()); + auto StartI = std::next(Stack.begin()); + auto EndI = Stack.end(); if (std::distance(StartI, EndI) <= (int)Level) return false; std::advance(StartI, Level); return DPred(StartI->Directive); } -template <class NamedDirectivesPredicate> -bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) { +bool DSAStackTy::hasDirective( + const llvm::function_ref<bool(OpenMPDirectiveKind, + const DeclarationNameInfo &, SourceLocation)> + &DPred, + bool FromParent) { auto StartI = std::next(Stack.rbegin()); auto EndI = std::prev(Stack.rend()); if (FromParent && StartI != EndI) { @@ -808,31 +807,22 @@ bool DSAStackTy::hasDirective(NamedDirectivesPredicate DPred, bool FromParent) { return false; } -OpenMPDirectiveKind DSAStackTy::getDirectiveForScope(const Scope *S) const { - for (auto I = Stack.rbegin(), EE = Stack.rend(); I != EE; ++I) - if (I->CurScope == S) - return I->Directive; - return OMPD_unknown; -} - void Sema::InitDataSharingAttributesStack() { VarDataSharingAttributesStack = new DSAStackTy(*this); } #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) -bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, - const CapturedRegionScopeInfo *RSI) { +bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); auto &Ctx = getASTContext(); bool IsByRef = true; // Find the directive that is associated with the provided scope. - auto DKind = DSAStack->getDirectiveForScope(RSI->TheScope); auto Ty = D->getType(); - if (isOpenMPTargetExecutionDirective(DKind)) { + if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) { // This table summarizes how a given variable should be passed to the device // given its type and the clauses where it appears. This table is based on // the description in OpenMP 4.5 [2.10.4, target Construct] and @@ -936,6 +926,12 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, } } + if (IsByRef && Ty.getNonReferenceType()->isScalarType()) { + IsByRef = !DSAStack->hasExplicitDSA( + D, [](OpenMPClauseKind K) -> bool { return K == OMPC_firstprivate; }, + Level, /*NotLastprivate=*/true); + } + // When passing data by copy, we need to make sure it fits the uintptr size // and alignment, because the runtime library only deals with uintptr types. // If it does not fit the uintptr size, we need to pass the data by reference @@ -943,12 +939,18 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) > Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || - Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) + Ctx.getDeclAlign(D) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) { IsByRef = true; + } return IsByRef; } +unsigned Sema::getOpenMPNestingLevel() const { + assert(getLangOpts().OpenMP); + return DSAStack->getNestingLevel(); +} + VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) { assert(LangOpts.OpenMP && "OpenMP is not allowed"); D = getCanonicalDecl(D); @@ -967,8 +969,8 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) { return VD; if (DSAStack->getCurScope() && DSAStack->hasDirective( - [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI, - SourceLocation Loc) -> bool { + [](OpenMPDirectiveKind K, const DeclarationNameInfo &, + SourceLocation) -> bool { return isOpenMPTargetExecutionDirective(K); }, false)) @@ -987,8 +989,9 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) { auto DVarPrivate = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind)) return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl()); - DVarPrivate = DSAStack->hasDSA(D, isOpenMPPrivate, MatchesAlways(), - DSAStack->isClauseParsingMode()); + DVarPrivate = DSAStack->hasDSA( + D, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; }, + DSAStack->isClauseParsingMode()); if (DVarPrivate.CKind != OMPC_unknown) return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl()); } @@ -1462,13 +1465,13 @@ public: // A list item that appears in a reduction clause of the innermost // enclosing worksharing or parallel construct may not be accessed in an // explicit task. - DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), - [](OpenMPDirectiveKind K) -> bool { - return isOpenMPParallelDirective(K) || - isOpenMPWorksharingDirective(K) || - isOpenMPTeamsDirective(K); - }, - false); + DVar = Stack->hasInnermostDSA( + VD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; }, + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPParallelDirective(K) || + isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); + }, + false); if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { ErrorFound = true; SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); @@ -1501,14 +1504,14 @@ public: // A list item that appears in a reduction clause of the innermost // enclosing worksharing or parallel construct may not be accessed in // an explicit task. - DVar = - Stack->hasInnermostDSA(FD, MatchesAnyClause(OMPC_reduction), - [](OpenMPDirectiveKind K) -> bool { - return isOpenMPParallelDirective(K) || - isOpenMPWorksharingDirective(K) || - isOpenMPTeamsDirective(K); - }, - false); + DVar = Stack->hasInnermostDSA( + FD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; }, + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPParallelDirective(K) || + isOpenMPWorksharingDirective(K) || + isOpenMPTeamsDirective(K); + }, + false); if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { ErrorFound = true; SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); @@ -2945,9 +2948,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // target exit data construct is encountered during execution of a // target region, the behavior is unspecified. NestingProhibited = Stack->hasDirective( - [&OffendingRegion](OpenMPDirectiveKind K, - const DeclarationNameInfo &DNI, - SourceLocation Loc) -> bool { + [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &, + SourceLocation) -> bool { if (isOpenMPTargetExecutionDirective(K)) { OffendingRegion = K; return true; @@ -4350,7 +4352,8 @@ static bool CheckOpenMPIterationSpace( // lastprivate (for simd directives with several collapsed or ordered // loops). if (DVar.CKind == OMPC_unknown) - DVar = DSA.hasDSA(LCDecl, isOpenMPPrivate, MatchesAlways(), + DVar = DSA.hasDSA(LCDecl, isOpenMPPrivate, + [](OpenMPDirectiveKind) -> bool { return true; }, /*FromParent=*/false); DSA.addDSA(LCDecl, LoopDeclRefExpr, PredeterminedCKind); } @@ -7800,13 +7803,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // encountered during execution of any of the worksharing regions arising // from the worksharing construct. if (isOpenMPTaskingDirective(CurrDir)) { - DVar = - DSAStack->hasInnermostDSA(D, MatchesAnyClause(OMPC_reduction), - [](OpenMPDirectiveKind K) -> bool { - return isOpenMPParallelDirective(K) || - isOpenMPWorksharingDirective(K); - }, - false); + DVar = DSAStack->hasInnermostDSA( + D, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; }, + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPParallelDirective(K) || + isOpenMPWorksharingDirective(K); + }, + false); if (DVar.CKind == OMPC_reduction && (isOpenMPParallelDirective(DVar.DKind) || isOpenMPWorksharingDirective(DVar.DKind))) { @@ -7831,21 +7834,23 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // A list item may appear in a firstprivate or lastprivate clause but not // both. if (CurrDir == OMPD_distribute) { - DVar = DSAStack->hasInnermostDSA(D, MatchesAnyClause(OMPC_private), - [](OpenMPDirectiveKind K) -> bool { - return isOpenMPTeamsDirective(K); - }, - false); + DVar = DSAStack->hasInnermostDSA( + D, [](OpenMPClauseKind C) -> bool { return C == OMPC_private; }, + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPTeamsDirective(K); + }, + false); if (DVar.CKind == OMPC_private && isOpenMPTeamsDirective(DVar.DKind)) { Diag(ELoc, diag::err_omp_firstprivate_distribute_private_teams); ReportOriginalDSA(*this, DSAStack, D, DVar); continue; } - DVar = DSAStack->hasInnermostDSA(D, MatchesAnyClause(OMPC_reduction), - [](OpenMPDirectiveKind K) -> bool { - return isOpenMPTeamsDirective(K); - }, - false); + DVar = DSAStack->hasInnermostDSA( + D, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; }, + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPTeamsDirective(K); + }, + false); if (DVar.CKind == OMPC_reduction && isOpenMPTeamsDirective(DVar.DKind)) { Diag(ELoc, diag::err_omp_firstprivate_distribute_in_teams_reduction); @@ -8105,8 +8110,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, IgnoredValueConversions(PostUpdateRes.get()).get()); } } - if (TopDVar.CKind != OMPC_firstprivate) - DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref); + DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref); Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref); SrcExprs.push_back(PseudoSrcExpr); DstExprs.push_back(PseudoDstExpr); @@ -8183,8 +8187,9 @@ public: return false; if (DVar.CKind != OMPC_unknown) return true; - DSAStackTy::DSAVarData DVarPrivate = - Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), false); + DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA( + VD, isOpenMPPrivate, [](OpenMPDirectiveKind) -> bool { return true; }, + false); if (DVarPrivate.CKind != OMPC_unknown) return true; return false; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f1377eb45ed..d2d4098d177 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3963,9 +3963,9 @@ StmtResult Sema::ActOnCapturedRegionEnd(Stmt *S) { CapturedDecl *CD = RSI->TheCapturedDecl; RecordDecl *RD = RSI->TheRecordDecl; - CapturedStmt *Res = CapturedStmt::Create(getASTContext(), S, - RSI->CapRegionKind, Captures, - CaptureInits, CD, RD); + CapturedStmt *Res = CapturedStmt::Create( + getASTContext(), S, static_cast<CapturedRegionKind>(RSI->CapRegionKind), + Captures, CaptureInits, CD, RD); CD->setBody(Res->getCapturedStmt()); RD->completeDefinition(); |