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"
@@ -1039,7 +1040,6 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
10391040 hasRequiresUnifiedSharedMemory(), /*HasRequiresDynamicAllocators*/ false);
10401041 Config.setDefaultTargetAS(
10411042 CGM.getContext().getTargetInfo().getTargetAddressSpace(LangAS::Default));
1042- Config.setRuntimeCC(CGM.getRuntimeCC());
10431043
10441044 OMPBuilder.setConfig(Config);
10451045 OMPBuilder.initialize();
@@ -7211,6 +7211,9 @@ class MappableExprsHandler {
72117211 /// firstprivate, false otherwise.
72127212 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
72137213
7214+ /// Set of defaultmap clause kinds that use firstprivate behavior.
7215+ llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7216+
72147217 /// Map between device pointer declarations and their expression components.
72157218 /// The key value for declarations in 'this' is null.
72167219 llvm::DenseMap<
@@ -8989,6 +8992,10 @@ class MappableExprsHandler {
89898992 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true);
89908993 }
89918994 }
8995+ // Extract defaultmap clause information.
8996+ for (const auto *C : Dir.getClausesOfKind<OMPDefaultmapClause>())
8997+ if (C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
8998+ DefaultmapFirstprivateKinds.insert(C->getDefaultmapKind());
89928999 // Extract device pointer clause information.
89939000 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
89949001 for (auto L : C->component_lists())
@@ -9566,6 +9573,36 @@ class MappableExprsHandler {
95669573 }
95679574 }
95689575
9576+ /// Check if a variable should be treated as firstprivate due to explicit
9577+ /// firstprivate clause or defaultmap(firstprivate:...).
9578+ bool isEffectivelyFirstprivate(const VarDecl *VD, QualType Type) const {
9579+ // Check explicit firstprivate clauses (not implicit from defaultmap)
9580+ auto I = FirstPrivateDecls.find(VD);
9581+ if (I != FirstPrivateDecls.end() && !I->getSecond())
9582+ return true; // Explicit firstprivate only
9583+
9584+ // Check defaultmap(firstprivate:scalar) for scalar types
9585+ if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
9586+ if (Type->isScalarType())
9587+ return true;
9588+ }
9589+
9590+ // Check defaultmap(firstprivate:pointer) for pointer types
9591+ if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
9592+ if (Type->isAnyPointerType())
9593+ return true;
9594+ }
9595+
9596+ // Check defaultmap(firstprivate:aggregate) for aggregate types
9597+ if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
9598+ if (Type->isAggregateType())
9599+ return true;
9600+ }
9601+
9602+ // Check defaultmap(firstprivate:all) for all types
9603+ return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
9604+ }
9605+
95699606 /// Generate the default map information for a given capture \a CI,
95709607 /// record field declaration \a RI and captured value \a CV.
95719608 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
@@ -9593,13 +9630,23 @@ class MappableExprsHandler {
95939630 CombinedInfo.DevicePtrDecls.push_back(nullptr);
95949631 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
95959632 CombinedInfo.Pointers.push_back(CV);
9633+ bool IsFirstprivate =
9634+ isEffectivelyFirstprivate(VD, RI.getType().getNonReferenceType());
9635+
95969636 if (!RI.getType()->isAnyPointerType()) {
95979637 // We have to signal to the runtime captures passed by value that are
95989638 // not pointers.
95999639 CombinedInfo.Types.push_back(
96009640 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
96019641 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
96029642 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
9643+ } else if (IsFirstprivate) {
9644+ // Firstprivate pointers should be passed by value (as literals)
9645+ // without performing a present table lookup at runtime.
9646+ CombinedInfo.Types.push_back(
9647+ OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9648+ // Use zero size for pointer literals (just passing the pointer value)
9649+ CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
96039650 } else {
96049651 // Pointers are implicitly mapped with a zero size and no flags
96059652 // (other than first map that is added for all implicit maps).
@@ -9613,26 +9660,31 @@ class MappableExprsHandler {
96139660 assert(CI.capturesVariable() && "Expected captured reference.");
96149661 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
96159662 QualType ElementType = PtrTy->getPointeeType();
9616- CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9617- CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
9618- // The default map type for a scalar/complex type is 'to' because by
9619- // default the value doesn't have to be retrieved. For an aggregate
9620- // type, the default is 'tofrom'.
9621- CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
96229663 const VarDecl *VD = CI.getCapturedVar();
9623- auto I = FirstPrivateDecls.find (VD);
9664+ bool IsFirstprivate = isEffectivelyFirstprivate (VD, ElementType );
96249665 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
96259666 CombinedInfo.BasePointers.push_back(CV);
96269667 CombinedInfo.DevicePtrDecls.push_back(nullptr);
96279668 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9628- if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
9629- Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
9630- CV, ElementType, CGF.getContext().getDeclAlign(VD),
9631- AlignmentSource::Decl));
9632- CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF));
9669+
9670+ // For firstprivate pointers, pass by value instead of dereferencing
9671+ if (IsFirstprivate && ElementType->isAnyPointerType()) {
9672+ // Treat as a literal value (pass the pointer value itself)
9673+ CombinedInfo.Pointers.push_back(CV);
9674+ // Use zero size for pointer literals
9675+ CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
9676+ CombinedInfo.Types.push_back(
9677+ OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
96339678 } else {
9679+ CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
9680+ CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
9681+ // The default map type for a scalar/complex type is 'to' because by
9682+ // default the value doesn't have to be retrieved. For an aggregate
9683+ // type, the default is 'tofrom'.
9684+ CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
96349685 CombinedInfo.Pointers.push_back(CV);
96359686 }
9687+ auto I = FirstPrivateDecls.find(VD);
96369688 if (I != FirstPrivateDecls.end())
96379689 IsImplicit = I->getSecond();
96389690 }
0 commit comments