2828#include "clang/Basic/SourceManager.h"
2929#include "clang/CodeGen/ConstantInitBuilder.h"
3030#include "llvm/ADT/ArrayRef.h"
31+ #include "llvm/ADT/SmallSet.h"
3132#include "llvm/ADT/SmallVector.h"
3233#include "llvm/ADT/StringExtras.h"
3334#include "llvm/Bitcode/BitcodeReader.h"
@@ -7211,6 +7212,9 @@ class MappableExprsHandler {
72117212 /// firstprivate, false otherwise.
72127213 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
72137214
7215+ /// Set of defaultmap clause kinds that use firstprivate behavior.
7216+ llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7217+
72147218 /// Map between device pointer declarations and their expression components.
72157219 /// The key value for declarations in 'this' is null.
72167220 llvm::DenseMap<
@@ -9007,6 +9011,10 @@ class MappableExprsHandler {
90079011 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true);
90089012 }
90099013 }
9014+ // Extract defaultmap clause information.
9015+ for (const auto *C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9016+ if (C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9017+ DefaultmapFirstprivateKinds.insert(C->getDefaultmapKind());
90109018 // Extract device pointer clause information.
90119019 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
90129020 for (auto L : C->component_lists())
@@ -9584,6 +9592,36 @@ class MappableExprsHandler {
95849592 }
95859593 }
95869594
9595+ /// Check if a variable should be treated as firstprivate due to explicit
9596+ /// firstprivate clause or defaultmap(firstprivate:...).
9597+ bool isEffectivelyFirstprivate(const VarDecl *VD, QualType Type) const {
9598+ // Check explicit firstprivate clauses (not implicit from defaultmap)
9599+ auto I = FirstPrivateDecls.find(VD);
9600+ if (I != FirstPrivateDecls.end() && !I->getSecond())
9601+ return true; // Explicit firstprivate only
9602+
9603+ // Check defaultmap(firstprivate:scalar) for scalar types
9604+ if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
9605+ if (Type->isScalarType())
9606+ return true;
9607+ }
9608+
9609+ // Check defaultmap(firstprivate:pointer) for pointer types
9610+ if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
9611+ if (Type->isAnyPointerType())
9612+ return true;
9613+ }
9614+
9615+ // Check defaultmap(firstprivate:aggregate) for aggregate types
9616+ if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
9617+ if (Type->isAggregateType())
9618+ return true;
9619+ }
9620+
9621+ // Check defaultmap(firstprivate:all) for all types
9622+ return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
9623+ }
9624+
95879625 /// Generate the default map information for a given capture \a CI,
95889626 /// record field declaration \a RI and captured value \a CV.
95899627 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
@@ -9611,13 +9649,23 @@ class MappableExprsHandler {
96119649 CombinedInfo.DevicePtrDecls.push_back(nullptr);
96129650 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
96139651 CombinedInfo.Pointers.push_back(CV);
9652+ bool IsFirstprivate =
9653+ isEffectivelyFirstprivate(VD, RI.getType().getNonReferenceType());
9654+
96149655 if (!RI.getType()->isAnyPointerType()) {
96159656 // We have to signal to the runtime captures passed by value that are
96169657 // not pointers.
96179658 CombinedInfo.Types.push_back(
96189659 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
96199660 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
96209661 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
9662+ } else if (IsFirstprivate) {
9663+ // Firstprivate pointers should be passed by value (as literals)
9664+ // without performing a present table lookup at runtime.
9665+ CombinedInfo.Types.push_back(
9666+ OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9667+ // Use zero size for pointer literals (just passing the pointer value)
9668+ CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
96219669 } else {
96229670 // Pointers are implicitly mapped with a zero size and no flags
96239671 // (other than first map that is added for all implicit maps).
@@ -9631,26 +9679,31 @@ class MappableExprsHandler {
96319679 assert(CI.capturesVariable() && "Expected captured reference.");
96329680 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
96339681 QualType ElementType = PtrTy->getPointeeType();
9634- CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9635- CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
9636- // The default map type for a scalar/complex type is 'to' because by
9637- // default the value doesn't have to be retrieved. For an aggregate
9638- // type, the default is 'tofrom'.
9639- CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
96409682 const VarDecl *VD = CI.getCapturedVar();
9641- auto I = FirstPrivateDecls.find (VD);
9683+ bool IsFirstprivate = isEffectivelyFirstprivate (VD, ElementType );
96429684 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
96439685 CombinedInfo.BasePointers.push_back(CV);
96449686 CombinedInfo.DevicePtrDecls.push_back(nullptr);
96459687 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9646- if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
9647- Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
9648- CV, ElementType, CGF.getContext().getDeclAlign(VD),
9649- AlignmentSource::Decl));
9650- CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF));
9688+
9689+ // For firstprivate pointers, pass by value instead of dereferencing
9690+ if (IsFirstprivate && ElementType->isAnyPointerType()) {
9691+ // Treat as a literal value (pass the pointer value itself)
9692+ CombinedInfo.Pointers.push_back(CV);
9693+ // Use zero size for pointer literals
9694+ CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
9695+ CombinedInfo.Types.push_back(
9696+ OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
96519697 } else {
9698+ CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9699+ CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
9700+ // The default map type for a scalar/complex type is 'to' because by
9701+ // default the value doesn't have to be retrieved. For an aggregate
9702+ // type, the default is 'tofrom'.
9703+ CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
96529704 CombinedInfo.Pointers.push_back(CV);
96539705 }
9706+ auto I = FirstPrivateDecls.find(VD);
96549707 if (I != FirstPrivateDecls.end())
96559708 IsImplicit = I->getSecond();
96569709 }
0 commit comments