diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 89 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 16 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 198 |
4 files changed, 228 insertions, 78 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 42b7d16dfdb..fb2ce6c16d0 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -862,18 +862,7 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, } LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { - if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) - return CGF.EmitOMPArraySectionExpr(OASE); - if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) - return CGF.EmitLValue(ASE); - auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), - CGF.CapturedStmtInfo && - CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr, - E->getType(), VK_LValue, E->getExprLoc()); - // Store the address of the original variable associated with the LHS - // implicit variable. - return CGF.EmitLValue(&DRE); + return CGF.EmitOMPSharedLValue(E); } LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, @@ -5978,6 +5967,8 @@ public: OMP_MAP_PRIVATE_PTR = 0x80, /// \brief Pass the element to the device by value. OMP_MAP_PRIVATE_VAL = 0x100, + /// Implicit map + OMP_MAP_IMPLICIT = 0x200, }; /// Class that associates information with a base pointer to be passed to the @@ -6148,7 +6139,7 @@ private: OMPClauseMappableExprCommon::MappableExprComponentListRef Components, MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, - bool IsFirstComponentList) const { + bool IsFirstComponentList, bool IsImplicit) const { // The following summarizes what has to be generated for each map and the // types bellow. The generated information is expressed in this order: @@ -6283,8 +6274,7 @@ private: } else { // The base is the reference to the variable. // BP = &Var. - BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression())) - .getPointer(); + BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer(); // If the variable is a pointer and is being dereferenced (i.e. is not // the last component), the base has to be the pointer itself, not its @@ -6303,6 +6293,7 @@ private: } } + unsigned DefaultFlags = IsImplicit ? OMP_MAP_IMPLICIT : 0; for (; I != CE; ++I) { auto Next = std::next(I); @@ -6337,7 +6328,8 @@ private: isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && "Unexpected expression"); - auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer(); + llvm::Value *LB = + CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer(); auto *Size = getExprTypeSize(I->getAssociatedExpression()); // If we have a member expression and the current component is a @@ -6352,9 +6344,11 @@ private: BasePointers.push_back(BP); Pointers.push_back(RefAddr); Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); - Types.push_back(getMapTypeBits( - /*MapType*/ OMPC_MAP_alloc, /*MapTypeModifier=*/OMPC_MAP_unknown, - !IsExpressionFirstInfo, IsCaptureFirstInfo)); + Types.push_back(DefaultFlags | + getMapTypeBits( + /*MapType*/ OMPC_MAP_alloc, + /*MapTypeModifier=*/OMPC_MAP_unknown, + !IsExpressionFirstInfo, IsCaptureFirstInfo)); IsExpressionFirstInfo = false; IsCaptureFirstInfo = false; // The reference will be the next base address. @@ -6369,9 +6363,9 @@ private: // same expression except for the first one. We also need to signal // this map is the first one that relates with the current capture // (there is a set of entries for each capture). - Types.push_back(getMapTypeBits(MapType, MapTypeModifier, - !IsExpressionFirstInfo, - IsCaptureFirstInfo)); + Types.push_back(DefaultFlags | getMapTypeBits(MapType, MapTypeModifier, + !IsExpressionFirstInfo, + IsCaptureFirstInfo)); // If we have a final array section, we are done with this expression. if (IsFinalArraySection) @@ -6383,7 +6377,6 @@ private: IsExpressionFirstInfo = false; IsCaptureFirstInfo = false; - continue; } } } @@ -6445,20 +6438,19 @@ public: RPK_MemberReference, }; OMPClauseMappableExprCommon::MappableExprComponentListRef Components; - OpenMPMapClauseKind MapType; - OpenMPMapClauseKind MapTypeModifier; - ReturnPointerKind ReturnDevicePointer; + OpenMPMapClauseKind MapType = OMPC_MAP_unknown; + OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + ReturnPointerKind ReturnDevicePointer = RPK_None; + bool IsImplicit = false; - MapInfo() - : MapType(OMPC_MAP_unknown), MapTypeModifier(OMPC_MAP_unknown), - ReturnDevicePointer(RPK_None) {} + MapInfo() = default; MapInfo( OMPClauseMappableExprCommon::MappableExprComponentListRef Components, OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, - ReturnPointerKind ReturnDevicePointer) + ReturnPointerKind ReturnDevicePointer, bool IsImplicit) : Components(Components), MapType(MapType), MapTypeModifier(MapTypeModifier), - ReturnDevicePointer(ReturnDevicePointer) {} + ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} }; // We have to process the component lists that relate with the same @@ -6472,25 +6464,29 @@ public: const ValueDecl *D, OMPClauseMappableExprCommon::MappableExprComponentListRef L, OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier, - MapInfo::ReturnPointerKind ReturnDevicePointer) { + MapInfo::ReturnPointerKind ReturnDevicePointer, bool IsImplicit) { const ValueDecl *VD = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; - Info[VD].push_back({L, MapType, MapModifier, ReturnDevicePointer}); + Info[VD].emplace_back(L, MapType, MapModifier, ReturnDevicePointer, + IsImplicit); }; // FIXME: MSVC 2013 seems to require this-> to find member CurDir. for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) - for (auto L : C->component_lists()) + for (auto L : C->component_lists()) { InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(), - MapInfo::RPK_None); + MapInfo::RPK_None, C->isImplicit()); + } for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>()) - for (auto L : C->component_lists()) + for (auto L : C->component_lists()) { InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown, - MapInfo::RPK_None); + MapInfo::RPK_None, C->isImplicit()); + } for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>()) - for (auto L : C->component_lists()) + for (auto L : C->component_lists()) { InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown, - MapInfo::RPK_None); + MapInfo::RPK_None, C->isImplicit()); + } // Look at the use_device_ptr clause information and mark the existing map // entries as such. If there is no map information for an entry in the @@ -6551,9 +6547,9 @@ public: // Remember the current base pointer index. unsigned CurrentBasePointersIdx = BasePointers.size(); // FIXME: MSVC 2013 seems to require this-> to find the member method. - this->generateInfoForComponentList(L.MapType, L.MapTypeModifier, - L.Components, BasePointers, Pointers, - Sizes, Types, IsFirstComponentList); + this->generateInfoForComponentList( + L.MapType, L.MapTypeModifier, L.Components, BasePointers, Pointers, + Sizes, Types, IsFirstComponentList, L.IsImplicit); // If this entry relates with a device pointer, set the relevant // declaration and add the 'return pointer' flag. @@ -6617,7 +6613,8 @@ public: for (auto L : It->second) { generateInfoForComponentList( /*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L, - BasePointers, Pointers, Sizes, Types, IsFirstComponentList); + BasePointers, Pointers, Sizes, Types, IsFirstComponentList, + /*IsImplicit=*/false); IsFirstComponentList = false; } return; @@ -6637,9 +6634,9 @@ public: "We got information for the wrong declaration??"); assert(!L.second.empty() && "Not expecting declaration with no component lists."); - generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(), - L.second, BasePointers, Pointers, Sizes, - Types, IsFirstComponentList); + generateInfoForComponentList( + C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers, + Pointers, Sizes, Types, IsFirstComponentList, C->isImplicit()); IsFirstComponentList = false; } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 4dcdaa29379..20f15352098 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -138,6 +138,22 @@ public: } // namespace +LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) { + if (auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) { + if (auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) { + OrigVD = OrigVD->getCanonicalDecl(); + bool IsCaptured = + LambdaCaptureFields.lookup(OrigVD) || + (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) || + (CurCodeDecl && isa<BlockDecl>(CurCodeDecl)); + DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), IsCaptured, + OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc()); + return EmitLValue(&DRE); + } + } + return EmitLValue(E); +} + llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) { auto &C = getContext(); llvm::Value *Size = nullptr; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index d77cea48b02..635df4bc6b5 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2886,6 +2886,9 @@ public: const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds); + /// Emits the lvalue for the expression with possibly captured variable. + LValue EmitOMPSharedLValue(const Expr *E); + private: /// Helpers for blocks llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index e4a57db8da5..735e827eeae 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -35,6 +35,11 @@ using namespace clang; // Stack of data-sharing attributes for variables //===----------------------------------------------------------------------===// +static Expr *CheckMapClauseExpressionBase( + Sema &SemaRef, Expr *E, + OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, + OpenMPClauseKind CKind); + namespace { /// \brief Default data sharing attributes, which can be applied to directive. enum DefaultDataSharingAttributes { @@ -1787,6 +1792,7 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> { bool ErrorFound; CapturedStmt *CS; llvm::SmallVector<Expr *, 8> ImplicitFirstprivate; + llvm::SmallVector<Expr *, 8> ImplicitMap; llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA; llvm::DenseSet<ValueDecl *> ImplicitDeclarations; @@ -1819,6 +1825,50 @@ public: return; } + if (isOpenMPTargetExecutionDirective(DKind) && + !Stack->isLoopControlVariable(VD).first) { + if (!Stack->checkMappableExprComponentListsForDecl( + VD, /*CurrentRegionOnly=*/true, + [](OMPClauseMappableExprCommon::MappableExprComponentListRef + StackComponents, + OpenMPClauseKind) { + // Variable is used if it has been marked as an array, array + // section or the variable iself. + return StackComponents.size() == 1 || + std::all_of( + std::next(StackComponents.rbegin()), + StackComponents.rend(), + [](const OMPClauseMappableExprCommon:: + MappableComponent &MC) { + return MC.getAssociatedDeclaration() == + nullptr && + (isa<OMPArraySectionExpr>( + MC.getAssociatedExpression()) || + isa<ArraySubscriptExpr>( + MC.getAssociatedExpression())); + }); + })) { + bool CapturedByCopy = false; + // By default lambdas are captured as firstprivates. + if (const auto *RD = + VD->getType().getNonReferenceType()->getAsCXXRecordDecl()) + if (RD->isLambda()) + CapturedByCopy = true; + CapturedByCopy = + CapturedByCopy || + llvm::any_of( + CS->captures(), [VD](const CapturedStmt::Capture &I) { + return I.capturesVariableByCopy() && + I.getCapturedVar()->getCanonicalDecl() == VD; + }); + if (CapturedByCopy) + ImplicitFirstprivate.emplace_back(E); + else + ImplicitMap.emplace_back(E); + return; + } + } + // OpenMP [2.9.3.6, Restrictions, p.2] // A list item that appears in a reduction clause of the innermost // enclosing worksharing or parallel construct may not be accessed in an @@ -1848,40 +1898,104 @@ public: if (E->isTypeDependent() || E->isValueDependent() || E->containsUnexpandedParameterPack() || E->isInstantiationDependent()) return; + auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl()); + if (!FD) + return; + OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) { - if (auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) { - auto DVar = Stack->getTopDSA(FD, false); - // Check if the variable has explicit DSA set and stop analysis if it - // so. - if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second) - return; + auto DVar = Stack->getTopDSA(FD, false); + // Check if the variable has explicit DSA set and stop analysis if it + // so. + if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second) + return; - auto ELoc = E->getExprLoc(); - auto DKind = Stack->getCurrentDirective(); - // OpenMP [2.9.3.6, Restrictions, p.2] - // 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, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; }, - [](OpenMPDirectiveKind K) -> bool { - return isOpenMPParallelDirective(K) || - isOpenMPWorksharingDirective(K) || - isOpenMPTeamsDirective(K); - }, - /*FromParent=*/true); - if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { - ErrorFound = true; - SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); - ReportOriginalDSA(SemaRef, Stack, FD, DVar); + if (isOpenMPTargetExecutionDirective(DKind) && + !Stack->isLoopControlVariable(FD).first && + !Stack->checkMappableExprComponentListsForDecl( + FD, /*CurrentRegionOnly=*/true, + [](OMPClauseMappableExprCommon::MappableExprComponentListRef + StackComponents, + OpenMPClauseKind) { + return isa<CXXThisExpr>( + cast<MemberExpr>( + StackComponents.back().getAssociatedExpression()) + ->getBase() + ->IgnoreParens()); + })) { + // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3] + // A bit-field cannot appear in a map clause. + // + if (FD->isBitField()) { + SemaRef.Diag(E->getMemberLoc(), + diag::err_omp_bit_fields_forbidden_in_clause) + << E->getSourceRange() << getOpenMPClauseName(OMPC_map); return; } + ImplicitMap.emplace_back(E); + return; + } - // Define implicit data-sharing attributes for task. - DVar = Stack->getImplicitDSA(FD, false); - if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared && - !Stack->isLoopControlVariable(FD).first) - ImplicitFirstprivate.push_back(E); + auto ELoc = E->getExprLoc(); + // OpenMP [2.9.3.6, Restrictions, p.2] + // 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, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; }, + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPParallelDirective(K) || + isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); + }, + /*FromParent=*/true); + if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) { + ErrorFound = true; + SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); + ReportOriginalDSA(SemaRef, Stack, FD, DVar); + return; + } + + // Define implicit data-sharing attributes for task. + DVar = Stack->getImplicitDSA(FD, false); + if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared && + !Stack->isLoopControlVariable(FD).first) + ImplicitFirstprivate.push_back(E); + return; + } + if (isOpenMPTargetExecutionDirective(DKind) && !FD->isBitField()) { + OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; + CheckMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map); + auto *VD = cast<ValueDecl>( + CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl()); + if (!Stack->checkMappableExprComponentListsForDecl( + VD, /*CurrentRegionOnly=*/true, + [&CurComponents]( + OMPClauseMappableExprCommon::MappableExprComponentListRef + StackComponents, + OpenMPClauseKind) { + if (CurComponents.size() < StackComponents.size()) + return false; + auto CCI = CurComponents.rbegin(); + for (const auto &SC : llvm::reverse(StackComponents)) { + // Do both expressions have the same kind? + if (CCI->getAssociatedExpression()->getStmtClass() != + SC.getAssociatedExpression()->getStmtClass()) + if (!(isa<OMPArraySectionExpr>( + SC.getAssociatedExpression()) && + isa<ArraySubscriptExpr>( + CCI->getAssociatedExpression()))) + return false; + + Decl *CCD = CCI->getAssociatedDeclaration(); + Decl *SCD = SC.getAssociatedDeclaration(); + CCD = CCD ? CCD->getCanonicalDecl() : nullptr; + SCD = SCD ? SCD->getCanonicalDecl() : nullptr; + if (SCD != CCD) + return false; + std::advance(CCI, 1); + } + return true; + })) { + Visit(E->getBase()); } } else Visit(E->getBase()); @@ -1889,12 +2003,16 @@ public: void VisitOMPExecutableDirective(OMPExecutableDirective *S) { for (auto *C : S->clauses()) { // Skip analysis of arguments of implicitly defined firstprivate clause - // for task directives. - if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid())) + // for task|target directives. + // Skip analysis of arguments of implicitly defined map clause for target + // directives. + if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) && + C->isImplicit())) { for (auto *CC : C->children()) { if (CC) Visit(CC); } + } } } void VisitStmt(Stmt *S) { @@ -1905,7 +2023,10 @@ public: } bool isErrorFound() { return ErrorFound; } - ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; } + ArrayRef<Expr *> getImplicitFirstprivate() const { + return ImplicitFirstprivate; + } + ArrayRef<Expr *> getImplicitMap() const { return ImplicitMap; } llvm::DenseMap<ValueDecl *, Expr *> &getVarsWithInheritedDSA() { return VarsWithInheritedDSA; } @@ -2638,6 +2759,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( SmallVector<Expr *, 4> ImplicitFirstprivates( DSAChecker.getImplicitFirstprivate().begin(), DSAChecker.getImplicitFirstprivate().end()); + SmallVector<Expr *, 4> ImplicitMaps(DSAChecker.getImplicitMap().begin(), + DSAChecker.getImplicitMap().end()); // Mark taskgroup task_reduction descriptors as implicitly firstprivate. for (auto *C : Clauses) { if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) { @@ -2656,6 +2779,17 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( } else ErrorFound = true; } + if (!ImplicitMaps.empty()) { + if (OMPClause *Implicit = ActOnOpenMPMapClause( + OMPC_MAP_unknown, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true, + SourceLocation(), SourceLocation(), ImplicitMaps, + SourceLocation(), SourceLocation(), SourceLocation())) { + ClausesWithImplicit.emplace_back(Implicit); + ErrorFound |= + cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size(); + } else + ErrorFound = true; + } } llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers; |