[clang] [OpenMP][wip] Rework 'containing struct'/overlapped mapping handling (PR #153672)
Julian Brown via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 14 13:34:02 PDT 2025
https://github.com/jtb20 created https://github.com/llvm/llvm-project/pull/153672
This patch is an early outline for a rework of several mapping features, intended to support 'containing structures' in the middle of expressions as well as at the top level (https://github.com/llvm/llvm-project/issues/141042). Key ideas are:
- struct information is gathered using several pre-passes before `generateInfoForComponentList`.
- "PartialStruct" is turned into a map, keyed on the "effective base" of each containing structure in a set of expressions in OpenMP 'map' clauses.
- the reverse iterator over component lists (visiting the base decl, then walking out to the full expression) has a new 'ComponentListRefPtrPteeIterator' adapter that (a) visits reference-type list components twice, and (b) provides a few useful utility methods.
The current state is that a couple of tests work up to a point, but I'm hitting problems with the runtime that will probably be helped by the in-progress patches to support ATTACH operations.
This is obviously all full of debug code and not at all ready for review! Posting FYI.
>From 806a34cf4ef936f22d0738f9bf34446b54d9fa21 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 24 Jul 2025 09:35:36 -0500
Subject: [PATCH 1/3] [OpenMP] Fix initialization order for
CopyOverlappedEntryGaps
NFC.
---
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index f1698a0bec373..91237cfe3a372 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7108,8 +7108,8 @@ class MappableExprsHandler {
Address BP, Address LB, bool IsNonContiguous,
uint64_t DimSize)
: CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
- MapExpr(MapExpr), BP(BP), LB(LB), IsNonContiguous(IsNonContiguous),
- DimSize(DimSize) {}
+ MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
+ DimSize(DimSize), LB(LB) {}
void processField(
const OMPClauseMappableExprCommon::MappableComponent &MC,
>From a0b521344ba96cd47b70dca969ae836579c29dfc Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Tue, 10 Jun 2025 08:11:06 -0500
Subject: [PATCH 2/3] Revert "[Clang][OpenMP] Fix mapping of structs to device
(#75642)"
This reverts commit 4ef6587715bec4520332528c4a71fe5a9ac10477.
---
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 116 +++++---------------------
1 file changed, 20 insertions(+), 96 deletions(-)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 91237cfe3a372..3bfb01cccf1a0 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7193,10 +7193,8 @@ class MappableExprsHandler {
OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
- MapCombinedInfoTy &CombinedInfo,
- MapCombinedInfoTy &StructBaseCombinedInfo,
- StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
- bool IsImplicit, bool GenerateAllInfoForClauses,
+ MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct,
+ bool IsFirstComponentList, bool IsImplicit,
const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false,
const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
@@ -7493,25 +7491,6 @@ class MappableExprsHandler {
bool IsPartialMapped =
!PartialStruct.PreliminaryMapData.BasePointers.empty();
- // We need to check if we will be encountering any MEs. If we do not
- // encounter any ME expression it means we will be mapping the whole struct.
- // In that case we need to skip adding an entry for the struct to the
- // CombinedInfo list and instead add an entry to the StructBaseCombinedInfo
- // list only when generating all info for clauses.
- bool IsMappingWholeStruct = true;
- if (!GenerateAllInfoForClauses) {
- IsMappingWholeStruct = false;
- } else {
- for (auto TempI = I; TempI != CE; ++TempI) {
- const MemberExpr *PossibleME =
- dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
- if (PossibleME) {
- IsMappingWholeStruct = false;
- break;
- }
- }
- }
-
for (; I != CE; ++I) {
// If the current component is member of a struct (parent struct) mark it.
if (!EncounteredME) {
@@ -7701,7 +7680,6 @@ class MappableExprsHandler {
// PartialStruct.PreliminaryMapData.BasePointers has been mapped.
if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
(Next == CE && MapType != OMPC_MAP_unknown)) {
- if (!IsMappingWholeStruct) {
CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
CombinedInfo.DevicePtrDecls.push_back(nullptr);
@@ -7711,26 +7689,9 @@ class MappableExprsHandler {
Size, CGF.Int64Ty, /*isSigned=*/true));
CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
: 1);
- } else {
- StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
- StructBaseCombinedInfo.BasePointers.push_back(
- BP.emitRawPointer(CGF));
- StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr);
- StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
- StructBaseCombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF));
- StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
- Size, CGF.Int64Ty, /*isSigned=*/true));
- StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
- IsNonContiguous ? DimSize : 1);
- }
-
// If Mapper is valid, the last component inherits the mapper.
bool HasMapper = Mapper && Next == CE;
- if (!IsMappingWholeStruct)
- CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr);
- else
- StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
- : nullptr);
+ CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr);
// We need to add a pointer flag for each map that comes from the
// same expression except for the first one. We also need to signal
@@ -7764,10 +7725,7 @@ class MappableExprsHandler {
}
}
- if (!IsMappingWholeStruct)
- CombinedInfo.Types.push_back(Flags);
- else
- StructBaseCombinedInfo.Types.push_back(Flags);
+ CombinedInfo.Types.push_back(Flags);
}
// If we have encountered a member expression so far, keep track of the
@@ -8359,10 +8317,8 @@ class MappableExprsHandler {
for (const auto &Data : Info) {
StructRangeInfoTy PartialStruct;
- // Current struct information:
+ // Temporary generated information.
MapCombinedInfoTy CurInfo;
- // Current struct base information:
- MapCombinedInfoTy StructBaseCurInfo;
const Decl *D = Data.first;
const ValueDecl *VD = cast_or_null<ValueDecl>(D);
bool HasMapBasePtr = false;
@@ -8387,56 +8343,31 @@ class MappableExprsHandler {
// Remember the current base pointer index.
unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
- unsigned StructBasePointersIdx =
- StructBaseCurInfo.BasePointers.size();
CurInfo.NonContigInfo.IsNonContiguous =
L.Components.back().isNonContiguous();
generateInfoForComponentList(
L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
- CurInfo, StructBaseCurInfo, PartialStruct,
- /*IsFirstComponentList=*/false, L.IsImplicit,
- /*GenerateAllInfoForClauses*/ true, L.Mapper, L.ForDeviceAddr, VD,
- L.VarRef, /*OverlappedElements*/ {},
+ CurInfo, PartialStruct, /*IsFirstComponentList=*/false,
+ L.IsImplicit, /*GenerateAllInfoForClauses*/ true, L.Mapper,
+ L.ForDeviceAddr, VD, L.VarRef, /*OverlappedElements*/ {},
HasMapBasePtr && HasMapArraySec);
- // If this entry relates to a device pointer, set the relevant
+ // If this entry relates with a device pointer, set the relevant
// declaration and add the 'return pointer' flag.
if (L.ReturnDevicePointer) {
- // Check whether a value was added to either CurInfo or
- // StructBaseCurInfo and error if no value was added to either of
- // them:
- assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
- StructBasePointersIdx <
- StructBaseCurInfo.BasePointers.size()) &&
+ assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
"Unexpected number of mapped base pointers.");
- // Choose a base pointer index which is always valid:
const ValueDecl *RelevantVD =
L.Components.back().getAssociatedDeclaration();
assert(RelevantVD &&
"No relevant declaration related with device pointer??");
- // If StructBaseCurInfo has been updated this iteration then work on
- // the first new entry added to it i.e. make sure that when multiple
- // values are added to any of the lists, the first value added is
- // being modified by the assignments below (not the last value
- // added).
- if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
- StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
- RelevantVD;
- StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
- L.ForDeviceAddr ? DeviceInfoTy::Address
- : DeviceInfoTy::Pointer;
- StructBaseCurInfo.Types[StructBasePointersIdx] |=
- OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
- } else {
- CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
- CurInfo.DevicePointers[CurrentBasePointersIdx] =
- L.ForDeviceAddr ? DeviceInfoTy::Address
- : DeviceInfoTy::Pointer;
- CurInfo.Types[CurrentBasePointersIdx] |=
- OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
- }
+ CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
+ CurInfo.DevicePointers[CurrentBasePointersIdx] =
+ L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer;
+ CurInfo.Types[CurrentBasePointersIdx] |=
+ OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
}
}
}
@@ -8483,24 +8414,17 @@ class MappableExprsHandler {
CurInfo.Mappers.push_back(nullptr);
}
}
-
- // Unify entries in one list making sure the struct mapping precedes the
- // individual fields:
- MapCombinedInfoTy UnionCurInfo;
- UnionCurInfo.append(StructBaseCurInfo);
- UnionCurInfo.append(CurInfo);
-
// If there is an entry in PartialStruct it means we have a struct with
// individual members mapped. Emit an extra combined entry.
if (PartialStruct.Base.isValid()) {
- UnionCurInfo.NonContigInfo.Dims.push_back(0);
- // Emit a combined entry:
- emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
+ CurInfo.NonContigInfo.Dims.push_back(0);
+ emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
/*IsMapThis*/ !VD, OMPBuilder, VD);
}
- // We need to append the results of this capture to what we already have.
- CombinedInfo.append(UnionCurInfo);
+ // We need to append the results of this capture to what we already
+ // have.
+ CombinedInfo.append(CurInfo);
}
// Append data for use_device_ptr clauses.
CombinedInfo.append(UseDeviceDataCombinedInfo);
>From 67db4820e3fa4412c8e69be8091e3ca4332ee041 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 12 Jun 2025 08:20:12 -0500
Subject: [PATCH 3/3] [OpenMP][wip] Rework 'containing struct'/overlapped
mapping handling
This patch is an early outline for a rework of several
mapping features, intended to support 'containing structures'
in the middle of expressions as well as at the top level
(https://github.com/llvm/llvm-project/issues/141042). Key ideas are:
- struct information is gathered as several pre-passes before
generateInfoForComponentList.
- "PartialStruct" is turned into a map, keyed on the "effective base" of
each containing structure in a set of expressions in OpenMP 'map' clauses.
- the reverse iterator over component lists (visiting the
base decl, then walking out to the full expression) has a new
'ComponentListRefPtrPteeIterator' adapter that (a) visits reference-type
list components twice, and (b) provides a few useful utility methods.
The current state is that a couple of tests work up to a point, but
I'm hitting problems with the runtime that will probably be helped by
the in-progress patches to support ATTACH operations.
---
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 1384 ++++++++++++++++++++++---
1 file changed, 1265 insertions(+), 119 deletions(-)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 3bfb01cccf1a0..3587096f8c6ec 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -18,25 +18,32 @@
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "TargetInfo.h"
+#include "clang-c/Index.h"
#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/CodeGen/CodeGenABITypes.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/Frontend/OpenMP/OMPConstants.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Support/TypeSize.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
@@ -6755,6 +6762,51 @@ llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective(
return NumThreadsVal;
}
+class EffectiveBaseMapKey {
+ llvm::FoldingSetNodeID ID;
+ bool Indirect = false;
+
+public:
+ EffectiveBaseMapKey(ASTContext &Ctx, const Expr *EB, bool Ind) {
+ EB->Profile(ID, Ctx, /*Canonical=*/true);
+ Indirect = Ind;
+ }
+
+ EffectiveBaseMapKey(llvm::FoldingSetNodeID FromID) : ID(FromID) { }
+
+ llvm::FoldingSetNodeID getID() const { return ID; }
+ bool getIndirect() const { return Indirect; }
+};
+
+template <> struct llvm::DenseMapInfo<EffectiveBaseMapKey> {
+
+ static EffectiveBaseMapKey getEmptyKey() {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(std::numeric_limits<unsigned>::max());
+ return EffectiveBaseMapKey(ID);
+ }
+
+ static EffectiveBaseMapKey getTombstoneKey() {
+ llvm::FoldingSetNodeID ID;
+ for (unsigned I = 0; I < sizeof(ID) / sizeof(unsigned); ++I) {
+ ID.AddInteger(std::numeric_limits<unsigned>::max());
+ }
+ return EffectiveBaseMapKey(ID);
+ }
+
+ static unsigned getHashValue(const EffectiveBaseMapKey &Val) {
+ auto ID = Val.getID();
+ ID.AddBoolean(Val.getIndirect());
+ return ID.ComputeHash();
+ }
+
+ static bool isEqual(const EffectiveBaseMapKey &LHS,
+ const EffectiveBaseMapKey &RHS) {
+ return LHS.getID() == RHS.getID() &&
+ LHS.getIndirect() == RHS.getIndirect();
+ }
+};
+
namespace {
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
@@ -6787,7 +6839,6 @@ class MappableExprsHandler {
public:
MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr)
: MapDecl(MapDecl), MapExpr(MapExpr) {}
-
const ValueDecl *getMapDecl() const { return MapDecl; }
const Expr *getMapExpr() const { return MapExpr; }
};
@@ -6825,22 +6876,50 @@ class MappableExprsHandler {
}
};
+ struct MappableExprMetadata {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ const MapData *MD = nullptr;
+ bool CompleteExpression = false;
+ Address Base = Address::invalid();
+ Address Pointer = Address::invalid();
+
+ //MappableExprMetadata() {}
+
+ /*MappableExprMetadata(OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
+ const MapData *MD, bool CompleteExpression)
+ : Components(Components), MD(MD),
+ CompleteExpression(CompleteExpression) {}
+
+ MappableExprMetadata(MappableExprMetadata &Other) {
+
+ }*/
+ };
+
+ using ExprComponentMap = llvm::MapVector<EffectiveBaseMapKey, MappableExprMetadata>;
+
/// Map between a struct and the its lowest & highest elements which have been
/// mapped.
/// [ValueDecl *] --> {LE(FieldIndex, Pointer),
/// HE(FieldIndex, Pointer)}
struct StructRangeInfoTy {
- MapCombinedInfoTy PreliminaryMapData;
+ //MapCombinedInfoTy PreliminaryMapData;
+ const Expr *BaseExpr = nullptr;
+ ExprComponentMap ChildComponents;
+ unsigned MemberDepth = -1u;
std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
0, Address::invalid()};
std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
0, Address::invalid()};
Address Base = Address::invalid();
+ Address BaseAddr = Address::invalid();
Address LB = Address::invalid();
bool IsArraySection = false;
- bool HasCompleteRecord = false;
+ const MapData *ContainingStructMap = nullptr;
};
+ // A map from effective base addresses to struct range info for that base.
+ using PartialStructMap = llvm::DenseMap<EffectiveBaseMapKey, StructRangeInfoTy>;
+
private:
/// Kind that defines how a device pointer has to be returned.
struct MapInfo {
@@ -7113,16 +7192,20 @@ class MappableExprsHandler {
void processField(
const OMPClauseMappableExprCommon::MappableComponent &MC,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &Layout,
const FieldDecl *FD,
llvm::function_ref<LValue(CodeGenFunction &, const MemberExpr *)>
EmitMemberExprBase) {
- const RecordDecl *RD = FD->getParent();
- const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
- uint64_t FieldOffset = RL.getFieldOffset(FD->getFieldIndex());
+ uint64_t FieldOffset = CGF.getContext().toBits(CharUnits::fromQuantity(Layout[FD]));
uint64_t FieldSize =
CGF.getContext().getTypeSize(FD->getType().getCanonicalType());
Address ComponentLB = Address::invalid();
+ fprintf(stderr, "Process field: ");
+ MC.getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, " offset: %d index: %d cursor: %d\n", (int) FieldOffset, (int) FD->getFieldIndex(),
+ (int) Cursor);
+
if (FD->getType()->isLValueReferenceType()) {
const auto *ME = cast<MemberExpr>(MC.getAssociatedExpression());
LValue BaseLVal = EmitMemberExprBase(CGF, ME);
@@ -7133,8 +7216,6 @@ class MappableExprsHandler {
CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()).getAddress();
}
- if (!LastParent)
- LastParent = RD;
if (FD->getParent() == LastParent) {
if (FD->getFieldIndex() != LastIndex + 1)
copyUntilField(FD, ComponentLB);
@@ -7156,13 +7237,11 @@ class MappableExprsHandler {
copySizedChunk(LBPtr, Size);
}
- void copyUntilEnd(Address HB) {
- if (LastParent) {
- const ASTRecordLayout &RL =
- CGF.getContext().getASTRecordLayout(LastParent);
- if ((uint64_t)CGF.getContext().toBits(RL.getSize()) <= Cursor)
- return;
- }
+ void copyUntilEnd(Address HB, CharUnits TypeSize) {
+ fprintf(stderr, "copyUntilEnd: Cursor=%d TypeSize=%d\n",
+ (int) Cursor, (int) CGF.getContext().toBits(TypeSize));
+ if ((uint64_t)CGF.getContext().toBits(TypeSize) <= Cursor)
+ return;
llvm::Value *LBPtr = LB.emitRawPointer(CGF);
llvm::Value *Size = CGF.Builder.CreatePtrDiff(
CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF),
@@ -7184,6 +7263,544 @@ class MappableExprsHandler {
}
};
+ /// Given a MemberExpr \c ME, find the containing structure as understood by
+ /// OpenMP (OpenMP 6.0, "2 Glossary").
+ const Expr *getEffectiveBase(const MemberExpr *ME, const MemberExpr **IME, bool &Ind) const {
+ const Expr *Base = ME->getBase()->IgnoreParenImpCasts();
+
+ Ind = false;
+
+ /*fprintf(stderr, "getEffectiveBase, input=");
+ ME->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\nbase=");
+ Base->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");*/
+
+ // Strip off any outer "." member accesses first
+ while (const auto *MEB = dyn_cast<MemberExpr>(Base)) {
+ if (ME->isArrow() || Base->getType()->isReferenceType()) {
+ break;
+ } else {
+ ME = MEB;
+ if (IME)
+ *IME = ME;
+ Base = ME->getBase()->IgnoreParenImpCasts();
+ }
+ }
+
+ /*fprintf(stderr, "now base=");
+ Base->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");*/
+
+ if (ME->isArrow() || Base->getType()->isReferenceType()) {
+ Ind = true;
+ return Base;
+ }
+
+ return indirectOnce(Base, Ind);
+ }
+
+ // Iterate a component list from the base of an expression to the complete
+ // expression. Components which are references are visited twice: firstly
+ // as the pointer, second as the pointee.
+ struct ComponentListRefPtrPteeIterator {
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const OMPClauseMappableExprCommon::MappableComponent;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const OMPClauseMappableExprCommon::MappableComponent*;
+ using reference = const OMPClauseMappableExprCommon::MappableComponent&;
+
+ std::reverse_iterator<const OMPClauseMappableExprCommon::MappableComponent *> Pos;
+ bool RefPtee = false;
+ const ValueDecl *BaseDecl = nullptr;
+ // We repeat on references -- this is the position in the underlying list.
+ unsigned ComponentPos = 0;
+
+ ComponentListRefPtrPteeIterator(std::reverse_iterator<const OMPClauseMappableExprCommon::MappableComponent *> From) : Pos(From)
+ { }
+
+ reference operator*() const { return *Pos; }
+ pointer operator->() { return &*Pos; }
+
+ void setBaseDecl(const ValueDecl *Decl) {
+ BaseDecl = Decl;
+ }
+
+ bool isRefPtee() {
+ return RefPtee;
+ }
+
+ bool isRef() {
+ const OMPClauseMappableExprCommon::MappableComponent *Comp = &*Pos;
+ if (isa<MemberExpr>(Pos->getAssociatedExpression())) {
+ const ValueDecl *MapDecl = Comp->getAssociatedDeclaration();
+ assert(MapDecl && "Expected associated declaration for member expr");
+ return MapDecl->getType()->isLValueReferenceType();
+ }
+ return false;
+ }
+
+ bool isPointer(bool AllowDeref) {
+ const OMPClauseMappableExprCommon::MappableComponent *Comp = &*Pos;
+ const Expr *AE = Comp->getAssociatedExpression();
+ const auto *OASE = dyn_cast<ArraySectionExpr>(AE);
+ bool IsPointer =
+ isa<OMPArrayShapingExpr>(AE) ||
+ (OASE && ArraySectionExpr::getBaseOriginalType(OASE).getCanonicalType()->isAnyPointerType()) ||
+ AE->getType()->isAnyPointerType();
+
+ if (AllowDeref)
+ return IsPointer;
+ else if (!IsPointer)
+ return false;
+
+ if (const auto *UO = dyn_cast<UnaryOperator>(AE))
+ return UO->getOpcode() != UO_Deref;
+
+ return !isa<BinaryOperator>(AE);
+ }
+
+ unsigned getComponentPos() {
+ return ComponentPos;
+ }
+
+ ComponentListRefPtrPteeIterator& operator++() {
+ if (isRef()) {
+ if (!RefPtee)
+ RefPtee = true;
+ else {
+ RefPtee = false;
+ ++Pos;
+ }
+ } else {
+ RefPtee = false;
+ // This could skip to outermost MemberExprs (over ".").
+ ++Pos;
+ ++ComponentPos;
+ /*while (auto ME = dyn_cast<MemberExpr>(Pos->getAssociatedExpression()->IgnoreParenImpCasts())) {
+ if (ME->isArrow() || ME->getBase()->getType()->isReferenceType())
+ break;
+ else
+ ++Pos;
+ }*/
+ }
+ return *this;
+ }
+
+ ComponentListRefPtrPteeIterator operator++(int) {
+ ComponentListRefPtrPteeIterator tmp = *this;
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(const ComponentListRefPtrPteeIterator& a,
+ const ComponentListRefPtrPteeIterator& b) {
+ return a.Pos == b.Pos && a.RefPtee == b.RefPtee;
+ }
+
+ friend bool operator!=(const ComponentListRefPtrPteeIterator &a,
+ const ComponentListRefPtrPteeIterator &b) {
+ return a.Pos != b.Pos || a.RefPtee != b.RefPtee;
+ }
+ };
+
+ bool exprsEqual(Expr *One, Expr *Two) const {
+ if (One == nullptr || Two == nullptr)
+ return One == Two;
+
+ if (One->getStmtClass() != Two->getStmtClass())
+ return false;
+
+ llvm::FoldingSetNodeID ProfOne, ProfTwo;
+ One->Profile(ProfOne, CGF.getContext(), true);
+ Two->Profile(ProfTwo, CGF.getContext(), true);
+
+ return ProfOne == ProfTwo;
+ }
+
+ const Expr *indirectOnce(const Expr *E, bool &Ind) const {
+ Ind = false;
+
+ // Treat (*foo).bar the same as foo->bar
+ if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
+ if (UO->getOpcode() == UO_Deref) {
+ Ind = true;
+ return UO->getSubExpr()->IgnoreParenImpCasts();
+ }
+ }
+
+ // Treat foo[0].bar the same as foo->bar
+ while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+ const Expr *ArrayBase = ASE->getBase()->IgnoreParenImpCasts();
+ const Expr *Index = ASE->getIdx();
+ Expr::EvalResult Result;
+ if (!Index->EvaluateAsInt(Result, CGF.getContext())) {
+ return E;
+ }
+ llvm::APSInt ConstIndex = Result.Val.getInt();
+ if (ConstIndex == 0) {
+ Ind = true;
+ E = ArrayBase;
+ }
+ if (!E->getType()->isArrayType())
+ break;
+ }
+
+ // Treat foo[:1].bar & foo[0:1].bar the same as foo->bar
+ if (const auto *ASecE = dyn_cast<ArraySectionExpr>(E)) {
+ const Expr *ArrayBase = ASecE->getBase()->IgnoreParenImpCasts();
+ const Expr *LB = ASecE->getLowerBound();
+ const Expr *Len = ASecE->getLength();
+ bool LBZero = false, LenOne = false;
+ Expr::EvalResult Result;
+ if (!LB) {
+ LBZero = true;
+ } else if (LB->EvaluateAsInt(Result, CGF.getContext())) {
+ llvm::APSInt ConstLB = Result.Val.getInt();
+ if (ConstLB == 0)
+ LBZero = true;
+ }
+ if (Len && Len->EvaluateAsInt(Result, CGF.getContext())) {
+ llvm::APSInt ConstLen = Result.Val.getInt();
+ if (ConstLen == 1) {
+ LenOne = true;
+ }
+ }
+ if (LBZero && LenOne) {
+ Ind = true;
+ return ArrayBase;
+ }
+ }
+
+ return E;
+ }
+
+ bool componentsEqual(const OMPClauseMappableExprCommon::MappableComponent &One,
+ const OMPClauseMappableExprCommon::MappableComponent &Two) const {
+ if (One.isNonContiguous() != Two.isNonContiguous())
+ return false;
+
+ ValueDecl *DeclOne = One.getAssociatedDeclaration();
+ ValueDecl *DeclTwo = Two.getAssociatedDeclaration();
+
+ if (DeclOne == nullptr || DeclTwo == nullptr)
+ return DeclOne == DeclTwo;
+
+ if (DeclOne->getCanonicalDecl() != DeclTwo->getCanonicalDecl())
+ return false;
+
+ return exprsEqual(One.getAssociatedExpression(),
+ Two.getAssociatedExpression());
+ }
+
+ bool hasMemberExpr(const OMPClauseMappableExprCommon::MappableExprComponentListRef Components) const {
+ return llvm::any_of(Components, [](const OMPClauseMappableExprCommon::MappableComponent &M) {
+ return isa<MemberExpr>(M.getAssociatedExpression());
+ });
+ }
+
+ void gatherStructDataForComponentList(const MapData &MD, OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
+ MapCombinedInfoTy &CombinedInfo, PartialStructMap &PartialStructs,
+ bool IsImplicit, const ValueDecl *Mapper = nullptr,
+ const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr) const {
+ // Scan the components from the base to the complete expression.
+ auto CI = ComponentListRefPtrPteeIterator(Components.rbegin());
+ auto CE = ComponentListRefPtrPteeIterator(Components.rend());
+ auto I = CI;
+
+ I.setBaseDecl(BaseDecl);
+
+ Address BPP = Address::invalid();
+ Address BP = Address::invalid();
+
+ const Expr *AssocExpr = I->getAssociatedExpression();
+ /*const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
+ const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
+ const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);*/
+
+ auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
+ const MemberExpr *E) {
+ const Expr *BaseExpr = E->getBase();
+ // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a
+ // scalar.
+ LValue BaseLV;
+ if (E->isArrow()) {
+ LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
+ Address Addr =
+ CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo);
+ QualType PtrTy = BaseExpr->getType()->getPointeeType();
+ BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo);
+ } else {
+ BaseLV = CGF.EmitOMPSharedLValue(BaseExpr);
+ }
+ return BaseLV;
+ };
+
+ if (!hasMemberExpr(Components))
+ return;
+
+ /*
+ if (isa<MemberExpr>(AssocExpr)) {
+ // The base is the 'this' pointer. The content of the pointer is going
+ // to be the base of the field being mapped.
+ BP = CGF.LoadCXXThisAddress();
+ } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
+ (OASE &&
+ isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
+ BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
+ } else if (OAShE &&
+ isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
+ BP = Address(
+ CGF.EmitScalarExpr(OAShE->getBase()),
+ CGF.ConvertTypeForMem(OAShE->getBase()->getType()->getPointeeType()),
+ CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
+ } else {*/
+ // The base is the reference to the variable.
+ // BP = &Var.
+ fprintf(stderr, "Init new BP from ");
+ AssocExpr->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
+ BPP = Address::invalid();
+ QualType Ty = CI->getAssociatedDeclaration()->getType().getNonReferenceType();
+ if (Ty->isAnyPointerType()) {
+ BPP = BP;
+ BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+ }
+ //}
+
+ bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
+ // Maybe this needs to be "number of indirections". We want something
+ // similar to topological sort, but simpler.
+ unsigned MemberDepth = 0;
+
+ MemberExpr *FirstMemberExpr = nullptr;
+ MemberExpr *LastMemberExpr = nullptr;
+
+ for (; I != CE; ++I) {
+ StructRangeInfoTy *PartialStruct = nullptr;
+ bool Indirected = false;
+
+ //auto Next = std::next(I);
+ if (auto ME = dyn_cast<MemberExpr>(I->getAssociatedExpression()->IgnoreParenImpCasts())) {
+ /*if (!FirstMemberExpr) {
+ QualType Ty = CI->getAssociatedDeclaration()->getType().getNonReferenceType();
+ if (Ty->isAnyPointerType()) {
+ BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+ Indirected = true;
+ }
+ FirstMemberExpr = ME;
+ }*/
+ ++MemberDepth;
+ }
+
+ // Peek at the next outer expression to see if it's a "." member access
+ if (auto ME = dyn_cast<MemberExpr>(I->getAssociatedExpression()->IgnoreParenImpCasts())) {
+ auto Next = std::next(I);
+ if (Next != CE) {
+ if (auto NME = dyn_cast<MemberExpr>(Next->getAssociatedExpression()->IgnoreParenImpCasts())) {
+ if (!NME->isArrow())
+ continue;
+ }
+ }
+ /*QualType Ty = I->getAssociatedDeclaration()->getType().getNonReferenceType();
+ fprintf(stderr, "expr: ");
+ I->getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ bool Ind;
+ const Expr *EB = getEffectiveBase(ME, nullptr, Ind);
+ if (Ind) {
+ BPP = BP;
+ BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+ } else {
+ BPP = Address::invalid();
+ }*/
+ }
+
+ bool LastIter = std::next(I) == CE;
+
+ const auto *OASE =
+ dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
+ const auto *OAShE =
+ dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
+ const auto *UO =
+ dyn_cast<UnaryOperator>(I->getAssociatedExpression());
+ bool IsDeref = UO && UO->getOpcode() == UO_Deref;
+
+ // A final array section, is one whose length can't be proved to be one.
+ // If the map item is non-contiguous then we don't treat any array section
+ // as final array section.
+ bool IsFinalArraySection =
+ !IsNonContiguous &&
+ isFinalArraySectionExpression(I->getAssociatedExpression());
+
+ // If we have a declaration for the mapping use that, otherwise use
+ // the base declaration of the map clause.
+ const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
+ ? I->getAssociatedDeclaration()
+ : BaseDecl;
+
+ //if (OASE)
+ // ++DimSize;
+
+ if (LastIter || I.isRef() || I.isPointer(false) || IsFinalArraySection) {
+ Address LB = Address::invalid();
+ //Address LowestElem = Address::invalid();
+
+ if (OAShE) {
+ /*LowestElem = */LB =
+ Address(CGF.EmitScalarExpr(OAShE->getBase()),
+ CGF.ConvertTypeForMem(OAShE->getBase()->getType()->getPointeeType()),
+ CGF.getContext().getTypeAlignInChars(
+ OAShE->getBase()->getType()));
+ } else if (I.isRef()) {
+ const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
+ LValue BaseLVal = EmitMemberExprBase(CGF, ME);
+ /*LowestElem =*/
+ LB = CGF.EmitLValueForFieldInitialization(
+ BaseLVal, cast<FieldDecl>(MapDecl))
+ .getAddress();
+ if (I.isRefPtee())
+ LB = CGF.EmitLoadOfReferenceLValue(LB, MapDecl->getType())
+ .getAddress();
+ } else {
+ /*LowestElem = */LB =
+ CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
+ .getAddress();
+ fprintf(stderr, "Calculated LB from: ");
+ I->getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ }
+
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
+ const MemberExpr *IME = ME;
+ bool Ind;
+ const Expr *EB = getEffectiveBase(ME, &IME, Ind);
+ EffectiveBaseMapKey EBKey(CGF.getContext(), EB, Ind);
+ if (PartialStructs.find(EBKey) == PartialStructs.end()) {
+ PartialStructs[EBKey] = StructRangeInfoTy{};
+ }
+ PartialStruct = &PartialStructs[EBKey];
+ if (PartialStruct->MemberDepth == -1u)
+ PartialStruct->MemberDepth = MemberDepth;
+ else {
+ if (PartialStruct->MemberDepth > MemberDepth) {
+ fprintf(stderr, "Member depth changed! %u->%u\n",
+ PartialStruct->MemberDepth, MemberDepth);
+ }
+ }
+ const auto *FD = cast<FieldDecl>(IME->getMemberDecl());
+ unsigned FieldIndex = FD->getFieldIndex();
+
+ // FIXME: Inadequate.
+ //if (MemberDepth > 1) {
+ // QualType Ty = ME->getBase()->getType().getNonReferenceType();
+ // if (Ty->isAnyPointerType()) {
+ // fprintf(stderr, "Indirect BP\n");
+ // BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+ // }
+ // }
+
+ // Update info about the lowest and highest elements for this struct
+ if (!PartialStruct->Base.isValid()) {
+ PartialStruct->LowestElem = {FieldIndex, LB/*LowestElem*/};
+ if (IsFinalArraySection && OASE) {
+ Address HB =
+ CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
+ .getAddress();
+ PartialStruct->HighestElem = {FieldIndex, HB};
+ } else {
+ PartialStruct->HighestElem = {FieldIndex, LB/*LowestElem*/};
+ }
+ // This gets overridden (to the beginning of the struct) in the
+ // second pass, when we know if we're also mapping the whole struct.
+ PartialStruct->LB = LB;
+ fprintf(stderr, "Set partial struct base to BP\n");
+ PartialStruct->Base = BP;
+ PartialStruct->BaseAddr = BPP;
+ PartialStruct->BaseExpr = EB;
+ } else if (FieldIndex < PartialStruct->LowestElem.first) {
+ PartialStruct->LowestElem = {FieldIndex, LB/*LowestElem*/};
+ } else if (FieldIndex > PartialStruct->HighestElem.first) {
+ if (IsFinalArraySection && OASE) {
+ Address HB =
+ CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
+ .getAddress();
+ PartialStruct->HighestElem = {FieldIndex, HB};
+ } else {
+ PartialStruct->HighestElem = {FieldIndex, LB/*LowestElem*/};
+ }
+ }
+ LastMemberExpr = ME;
+ }
+
+ /*auto Next = std::next(I);
+ if (Next != CE) {
+ const Expr *NE = Next->getAssociatedExpression();
+ bool Ind;
+ const Expr *INE = indirectOnce(NE, Ind);
+ if (Ind) {
+ fprintf(stderr, "Indirected once, from: ");
+ NE->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\nto: ");
+ INE->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ if (isa<MemberExpr>(INE) ||
+ isa<DeclRefExpr>(INE)) {
+ fprintf(stderr, "continuing\n");
+ continue;
+ } else {
+ fprintf(stderr, "breaking\n");
+ break;
+ }
+ }
+ }*/
+
+ do {
+ if (isa<MemberExpr>(I->getAssociatedExpression()) || LastIter) {
+ EffectiveBaseMapKey IKey(CGF.getContext(), I->getAssociatedExpression(), false);
+ if (!PartialStruct) {
+ assert(LastIter && "only expected null PartialStruct on last iter");
+ if (!LastMemberExpr)
+ break;
+ bool Ind;
+ const Expr *EB = getEffectiveBase(LastMemberExpr, nullptr, Ind);
+ EffectiveBaseMapKey EBKey(CGF.getContext(), EB, Ind);
+ PartialStruct = &PartialStructs[EBKey];
+ }
+ if (PartialStruct->ChildComponents.find(IKey) == PartialStruct->ChildComponents.end()) {
+ int CutElems = Components.size() - I.getComponentPos() - 1;
+ ArrayRef<OMPClauseMappableExprCommon::MappableComponent> Tmp =
+ Components.drop_front(CutElems);
+ bool CompleteExpr = CutElems == 0;
+ auto CI = Tmp.rbegin();
+ auto CE = Tmp.rend();
+ auto I = CI;
+ fprintf(stderr, "Made a chopped list:\n");
+ for (; I != CE; ++I) {
+ I->getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ }
+ PartialStruct->ChildComponents[IKey] = {Tmp, &MD, CompleteExpr, BP, LB};
+ }
+ }
+ } while (false);
+
+ fprintf(stderr, "copy LB to BP\n");
+ BPP = LB;
+ QualType Ty = I->getAssociatedExpression()->getType().getCanonicalType();
+ if (Ty->isAnyPointerType()) {
+ BP = CGF.EmitLoadOfPointer(BPP, Ty->castAs<PointerType>());
+ } else {
+ fprintf(stderr, "Non-pointer BPP\n");
+ BP = BPP;
+ }
+ }
+ }
+ }
+
/// Generate the base pointers, section pointers, sizes, map type bits, and
/// user-defined mappers (all included in \a CombinedInfo) for the provided
/// map type, map or motion modifiers, and expression components.
@@ -7193,12 +7810,12 @@ class MappableExprsHandler {
OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
- MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct,
+ MapCombinedInfoTy &CombinedInfo, PartialStructMap &PartialStructs,
bool IsFirstComponentList, bool IsImplicit,
const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false,
const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
- ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
- OverlappedElements = {},
+ /*ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
+ OverlappedElements = {},*/
bool AreBothBasePtrAndPteeMapped = false) const {
// The following summarizes what has to be generated for each map and the
// types below. The generated information is expressed in this order:
@@ -7388,8 +8005,8 @@ class MappableExprsHandler {
bool RequiresReference = false;
// Scan the components from the base to the complete expression.
- auto CI = Components.rbegin();
- auto CE = Components.rend();
+ auto CI = ComponentListRefPtrPteeIterator(Components.rbegin());
+ auto CE = ComponentListRefPtrPteeIterator(Components.rend());
auto I = CI;
// Track if the map information being generated is the first for a list of
@@ -7402,22 +8019,35 @@ class MappableExprsHandler {
const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
+ fprintf(stderr, "generateInfoForComponentList\n");
+ //fprintf(stderr, "Preliminary data length: %d\n",
+ // (int) PartialStruct.PreliminaryMapData.Exprs.size());
+ fprintf(stderr, "Combined info length: %d\n",
+ (int) CombinedInfo.Exprs.size());
+
+ /* fprintf(stderr, "last component list entry:\n");
+ std::prev(CE)->getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");*/
+
if (AreBothBasePtrAndPteeMapped && std::next(I) == CE)
return;
if (isa<MemberExpr>(AssocExpr)) {
// The base is the 'this' pointer. The content of the pointer is going
// to be the base of the field being mapped.
BP = CGF.LoadCXXThisAddress();
+ assert(false && "unreachable 1");
} else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
(OASE &&
isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
+ assert(false && "unreachable 2");
} else if (OAShE &&
isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
BP = Address(
CGF.EmitScalarExpr(OAShE->getBase()),
CGF.ConvertTypeForMem(OAShE->getBase()->getType()->getPointeeType()),
CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
+ assert(false && "unreachable 3");
} else {
// The base is the reference to the variable.
// BP = &Var.
@@ -7488,8 +8118,8 @@ class MappableExprsHandler {
bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
bool IsPrevMemberReference = false;
- bool IsPartialMapped =
- !PartialStruct.PreliminaryMapData.BasePointers.empty();
+ //bool IsPartialMapped =
+ // !PartialStruct.PreliminaryMapData.BasePointers.empty();
for (; I != CE; ++I) {
// If the current component is member of a struct (parent struct) mark it.
@@ -7623,54 +8253,7 @@ class MappableExprsHandler {
(IsPrevMemberReference && !IsPointer) ||
(IsMemberReference && Next != CE &&
!Next->getAssociatedExpression()->getType()->isPointerType()));
- if (!OverlappedElements.empty() && Next == CE) {
- // Handle base element with the info for overlapped elements.
- assert(!PartialStruct.Base.isValid() && "The base element is set.");
- assert(!IsPointer &&
- "Unexpected base element with the pointer type.");
- // Mark the whole struct as the struct that requires allocation on the
- // device.
- PartialStruct.LowestElem = {0, LowestElem};
- CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
- I->getAssociatedExpression()->getType());
- Address HB = CGF.Builder.CreateConstGEP(
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- LowestElem, CGF.VoidPtrTy, CGF.Int8Ty),
- TypeSize.getQuantity() - 1);
- PartialStruct.HighestElem = {
- std::numeric_limits<decltype(
- PartialStruct.HighestElem.first)>::max(),
- HB};
- PartialStruct.Base = BP;
- PartialStruct.LB = LB;
- assert(
- PartialStruct.PreliminaryMapData.BasePointers.empty() &&
- "Overlapped elements must be used only once for the variable.");
- std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
- // Emit data for non-overlapped data.
- OpenMPOffloadMappingFlags Flags =
- OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
- getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
- /*AddPtrFlag=*/false,
- /*AddIsTargetParamFlag=*/false, IsNonContiguous);
- CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
- MapExpr, BP, LB, IsNonContiguous,
- DimSize);
- // Do bitcopy of all non-overlapped structure elements.
- for (OMPClauseMappableExprCommon::MappableExprComponentListRef
- Component : OverlappedElements) {
- for (const OMPClauseMappableExprCommon::MappableComponent &MC :
- Component) {
- if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
- if (const auto *FD = dyn_cast<FieldDecl>(VD)) {
- CopyGaps.processField(MC, FD, EmitMemberExprBase);
- }
- }
- }
- }
- CopyGaps.copyUntilEnd(HB);
- break;
- }
+
llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
// Skip adding an entry in the CurInfo of this combined entry if the
// whole struct is currently being mapped. The struct needs to be added
@@ -7678,7 +8261,7 @@ class MappableExprsHandler {
// mapped.
// Skip adding an entry in the CurInfo of this combined entry if the
// PartialStruct.PreliminaryMapData.BasePointers has been mapped.
- if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
+ if ((!IsMemberPointerOrAddr /*&& !IsPartialMapped*/) ||
(Next == CE && MapType != OMPC_MAP_unknown)) {
CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
@@ -7728,6 +8311,7 @@ class MappableExprsHandler {
CombinedInfo.Types.push_back(Flags);
}
+#if 0
// If we have encountered a member expression so far, keep track of the
// mapped member. If the parent is "*this", then the value declaration
// is nullptr.
@@ -7761,10 +8345,11 @@ class MappableExprsHandler {
}
}
}
+#endif
// Need to emit combined struct for array sections.
- if (IsFinalArraySection || IsNonContiguous)
- PartialStruct.IsArraySection = true;
+ //if (IsFinalArraySection || IsNonContiguous)
+ // PartialStruct.IsArraySection = true;
// If we have a final array section, we are done with this expression.
if (IsFinalArraySection)
@@ -7773,7 +8358,7 @@ class MappableExprsHandler {
// The pointer becomes the base for the next element.
if (Next != CE)
BP = IsMemberReference ? LowestElem : LB;
- if (!IsPartialMapped)
+ if (true /*!IsPartialMapped*/)
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
FirstPointerInComplexData = false;
@@ -7789,8 +8374,8 @@ class MappableExprsHandler {
}
// If ran into the whole component - allocate the space for the whole
// record.
- if (!EncounteredME)
- PartialStruct.HasCompleteRecord = true;
+ //if (!EncounteredME)
+ // PartialStruct.HasCompleteRecord = true;
if (!IsNonContiguous)
return;
@@ -8065,6 +8650,93 @@ class MappableExprsHandler {
}
}
+ void getFieldOffsets(const CXXRecordDecl *RD,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &Layout,
+ llvm::SmallPtrSetImpl<const CXXRecordDecl *> &Processed,
+ uint64_t ParentOffset,
+ bool AsBase) const {
+ const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
+
+ fprintf(stderr, "Getting field offsets for decl:\n");
+ RD->dump();
+
+ llvm::StructType *St =
+ AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
+ auto &DL = CGF.CGM.getDataLayout();
+ const llvm::StructLayout *SL =
+ DL.getStructLayout(St);
+
+ Processed.insert(RD);
+
+ unsigned NumElements = St->getNumElements();
+ llvm::SmallVector<
+ llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
+ RecordLayout(NumElements * 2);
+
+ // Fill bases.
+ for (const auto &I : RD->bases()) {
+ if (I.isVirtual())
+ continue;
+
+ QualType BaseTy = I.getType();
+ const auto *Base = BaseTy->getAsCXXRecordDecl();
+ // Ignore empty bases.
+ if (isEmptyRecordForLayout(CGF.getContext(), BaseTy) ||
+ CGF.getContext()
+ .getASTRecordLayout(Base)
+ .getNonVirtualSize()
+ .isZero())
+ continue;
+
+ unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
+ RecordLayout[FieldIndex] = Base;
+ }
+ assert(RD->vbases().empty() && "FIXME, virtual bases");
+ // Fill in all the fields.
+ assert(!RD->isUnion() && "Unexpected union.");
+ for (const auto *Field : RD->fields()) {
+ // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
+ // will fill in later.)
+ if (!Field->isBitField() &&
+ !isEmptyFieldForLayout(CGF.getContext(), Field)) {
+ unsigned FieldIndex = RL.getLLVMFieldNo(Field);
+ RecordLayout[FieldIndex] = Field;
+ if (Field->getType().getCanonicalType().getTypePtr()->isRecordType()) {
+ const CXXRecordDecl *RD2 = Field->getType().getCanonicalType().getTypePtr()->getAsCXXRecordDecl();
+ if (!Processed.contains(RD2)) {
+ llvm::TypeSize Offset = SL->getElementOffset(FieldIndex);
+ getFieldOffsets(RD2, Layout, Processed, ParentOffset + Offset, /*AsBase=*/true);
+ }
+ }
+ }
+ }
+ for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
+ &Data : RecordLayout) {
+ if (Data.isNull())
+ continue;
+ if (const auto *Base = dyn_cast<const CXXRecordDecl *>(Data)) {
+ if (RL.hasNonVirtualBaseLLVMField(Base)) {
+ unsigned FieldNo = RL.getNonVirtualBaseLLVMFieldNo(Base);
+ llvm::TypeSize Offset = SL->getElementOffset(FieldNo);
+ getFieldOffsets(Base, Layout, Processed, Offset, /*AsBase=*/true);
+ } else {
+ assert(false && "Unhandled virtual base");
+ }
+ } else {
+ const auto *FD = cast<const FieldDecl *>(Data);
+ //const auto *RD = FD->getParent();
+ unsigned FieldNo = RL.getLLVMFieldNo(FD);
+ llvm::TypeSize FieldOffset = SL->getElementOffset(FieldNo);
+ if (Layout.find(FD) == Layout.end()) {
+ Layout[FD] = ParentOffset + FieldOffset;
+ } else {
+ fprintf(stderr, "FD already in layout?\n");
+ }
+ }
+ }
+ fprintf(stderr, "Returning...\n");
+ }
+
/// Generate all the base pointers, section pointers, sizes, map types, and
/// mappers for the extracted mappable expressions (all included in \a
/// CombinedInfo). Also, for each item that relates with a device pointer, a
@@ -8083,6 +8755,8 @@ class MappableExprsHandler {
SmallVector<SmallVector<MapInfo, 8>, 4>>
Info;
+ fprintf(stderr, "generateAllInfoForClauses\n");
+
// Helper function to fill the information map for the different supported
// clauses.
auto &&InfoGen =
@@ -8316,7 +8990,7 @@ class MappableExprsHandler {
}
for (const auto &Data : Info) {
- StructRangeInfoTy PartialStruct;
+ PartialStructMap PartialStructs;
// Temporary generated information.
MapCombinedInfoTy CurInfo;
const Decl *D = Data.first;
@@ -8345,12 +9019,12 @@ class MappableExprsHandler {
unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
CurInfo.NonContigInfo.IsNonContiguous =
L.Components.back().isNonContiguous();
+ fprintf(stderr, "*** From generateAllInfoForClauses...\n");
generateInfoForComponentList(
L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
- CurInfo, PartialStruct, /*IsFirstComponentList=*/false,
- L.IsImplicit, /*GenerateAllInfoForClauses*/ true, L.Mapper,
- L.ForDeviceAddr, VD, L.VarRef, /*OverlappedElements*/ {},
- HasMapBasePtr && HasMapArraySec);
+ CurInfo, PartialStructs, /*IsFirstComponentList=*/false,
+ L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef,
+ /*OverlappedElements {},*/ HasMapBasePtr && HasMapArraySec);
// If this entry relates with a device pointer, set the relevant
// declaration and add the 'return pointer' flag.
@@ -8415,12 +9089,12 @@ class MappableExprsHandler {
}
}
// If there is an entry in PartialStruct it means we have a struct with
- // individual members mapped. Emit an extra combined entry.
- if (PartialStruct.Base.isValid()) {
- CurInfo.NonContigInfo.Dims.push_back(0);
- emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
- /*IsMapThis*/ !VD, OMPBuilder, VD);
- }
+ // individual members mapped. Emit an extra combined entry. FIXME.
+ //if (PartialStruct.Base.isValid()) {
+ // CurInfo.NonContigInfo.Dims.push_back(0);
+ // emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
+ // /*IsMapThis*/ !VD, OMPBuilder, VD);
+ // }
// We need to append the results of this capture to what we already
// have.
@@ -8489,7 +9163,8 @@ class MappableExprsHandler {
llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD = nullptr,
unsigned OffsetForMemberOfFlag = 0,
- bool NotTargetParams = true) const {
+ OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE) const {
+ fprintf(stderr, "emitCombinedEntry\n");
if (CurTypes.size() == 1 &&
((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
@@ -8497,13 +9172,16 @@ class MappableExprsHandler {
return;
Address LBAddr = PartialStruct.LowestElem.second;
Address HBAddr = PartialStruct.HighestElem.second;
- if (PartialStruct.HasCompleteRecord) {
+ if (PartialStruct.ContainingStructMap) {
LBAddr = PartialStruct.LB;
HBAddr = PartialStruct.LB;
}
CombinedInfo.Exprs.push_back(VD);
// Base is the base of the struct
- CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
+ if (Flags == OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ)
+ CombinedInfo.BasePointers.push_back(PartialStruct.BaseAddr.emitRawPointer(CGF));
+ else
+ CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
CombinedInfo.DevicePtrDecls.push_back(nullptr);
CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
// Pointer is the address of the lowest element
@@ -8542,11 +9220,11 @@ class MappableExprsHandler {
}
CombinedInfo.Mappers.push_back(nullptr);
// Map type is always TARGET_PARAM, if generate info for captures.
- CombinedInfo.Types.push_back(
- NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
- : !PartialStruct.PreliminaryMapData.BasePointers.empty()
- ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
- : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
+ CombinedInfo.Types.push_back(Flags);
+ //NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
+ //: /*!PartialStruct.PreliminaryMapData.BasePointers.empty()
+ // ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
+ // :*/ OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
// If any element has the present modifier, then make sure the runtime
// doesn't attempt to allocate the struct.
if (CurTypes.end() !=
@@ -8591,6 +9269,7 @@ class MappableExprsHandler {
MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
+ fprintf(stderr, "generateAllInfo\n");
assert(isa<const OMPExecutableDirective *>(CurDir) &&
"Expect a executable directive");
const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
@@ -8725,7 +9404,8 @@ class MappableExprsHandler {
/// \a CurCaptureVarInfo).
void generateInfoForCaptureFromClauseInfo(
const CapturedStmt::Capture *Cap, llvm::Value *Arg,
- MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
+ MapCombinedInfoTy &CurCaptureVarInfo, PartialStructMap &PartialStructs,
+ llvm::OpenMPIRBuilder &OMPBuilder,
unsigned OffsetForMemberOfFlag) const {
assert(!Cap->capturesVariableArrayType() &&
"Not expecting to generate map info for a variable array type!");
@@ -8740,6 +9420,8 @@ class MappableExprsHandler {
if (LambdasMap.count(VD))
return;
+ fprintf(stderr, "generateInfoForCapture\n");
+
// If this declaration appears in a is_device_ptr clause we just have to
// pass the pointer by value. If it is a reference to a declaration, we just
// pass its value.
@@ -8821,27 +9503,26 @@ class MappableExprsHandler {
[&](ArrayRef<MapData> DeclComponentLists,
bool IsEligibleForTargetParamFlag) {
MapCombinedInfoTy CurInfoForComponentLists;
- StructRangeInfoTy PartialStruct;
if (DeclComponentLists.empty())
return;
generateInfoForCaptureFromComponentLists(
- VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
+ OMPBuilder, VD, DeclComponentLists, CurInfoForComponentLists, PartialStructs,
IsEligibleForTargetParamFlag,
/*AreBothBasePtrAndPteeMapped=*/HasMapBasePtr && HasMapArraySec);
// If there is an entry in PartialStruct it means we have a
// struct with individual members mapped. Emit an extra combined
// entry.
- if (PartialStruct.Base.isValid()) {
- CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
- emitCombinedEntry(
- CurCaptureVarInfo, CurInfoForComponentLists.Types,
- PartialStruct, Cap->capturesThis(), OMPBuilder, nullptr,
- OffsetForMemberOfFlag,
- /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
- }
+ //if (PartialStruct.Base.isValid()) {
+ // CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
+ // emitCombinedEntry(
+ // CurCaptureVarInfo, CurInfoForComponentLists.Types,
+ // PartialStruct, Cap->capturesThis(), OMPBuilder, nullptr,
+ // OffsetForMemberOfFlag,
+ // /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
+ // }
// Return if we didn't add any entries.
if (CurInfoForComponentLists.BasePointers.empty())
@@ -8858,10 +9539,11 @@ class MappableExprsHandler {
/// mappers associated to \a DeclComponentLists for a given capture
/// \a VD (all included in \a CurComponentListInfo).
void generateInfoForCaptureFromComponentLists(
- const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
- MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
+ llvm::OpenMPIRBuilder &OMPBuilder, const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
+ MapCombinedInfoTy &CurComponentListInfo, PartialStructMap &PartialStructs,
bool IsListEligibleForTargetParamFlag,
bool AreBothBasePtrAndPteeMapped = false) const {
+#if 0
// Find overlapping elements (including the offset from the base element).
llvm::SmallDenseMap<
const MapData *,
@@ -8982,11 +9664,421 @@ class MappableExprsHandler {
return *It == FD1;
});
}
+ #endif
+
+ fprintf(stderr, "Gather structs, pass 1\n");
+
+ // Pass 1: Gather data about structs (effective bases, low-high ranges)
+ for (const MapData &L : DeclComponentLists) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ const ValueDecl *Mapper;
+ const Expr *MapExpr;
+ std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, MapExpr) =
+ L;
+ gatherStructDataForComponentList(L, MapType, MapModifiers, Components,
+ CurComponentListInfo, PartialStructs,
+ IsImplicit, Mapper, VD, MapExpr);
+ }
+ fprintf(stderr, "Gather structs, pass 2\n");
+
+ llvm::SmallPtrSet<const MapData *, 8> ProcessedMappings;
+
+ // Pass 2: Find whole-struct mappings which overlap with member accesses.
+ // This only handles fairly simple cases, and will fail for things like:
+ // map(tofrom: arr[5]) map(tofrom: arr[5].x)
+ // That could probably be improved a bit.
+ for (const MapData &L : DeclComponentLists) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ const ValueDecl *Mapper;
+ const Expr *MapExpr;
+ std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, MapExpr) =
+ L;
+ const Expr *MapExprOrig = MapExpr;
+ if (const auto *UO = dyn_cast<UnaryOperator>(MapExpr)) {
+ if (UO->getOpcode() == UO_Deref) {
+ MapExpr = UO->getSubExpr()->IgnoreParenImpCasts();
+ }
+ } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(MapExpr)) {
+ const Expr *ArrayBase = ASE->getBase()->IgnoreParenImpCasts();
+ const Expr *Index = ASE->getIdx();
+ Expr::EvalResult Result;
+ if (Index->EvaluateAsInt(Result, CGF.getContext())) {
+ llvm::APSInt ConstIndex = Result.Val.getInt();
+ if (ConstIndex == 0) {
+ MapExpr = ArrayBase;
+ }
+ }
+ } else if (const auto *ASecE = dyn_cast<ArraySectionExpr>(MapExpr)) {
+ const Expr *ArrayBase = ASecE->getBase()->IgnoreParenImpCasts();
+ // In general, we can't tell if we're mapping the whole struct here,
+ // so this is somewhat best-effort.
+ // Maybe this should be a compile-time warning, or we should arrange
+ // so the runtime does the right thing regardless (e.g. with
+ // potentially redundant mappings).
+ bool CheckLength = false;
+ if (!ASecE->getLowerBound())
+ CheckLength = true;
+ else {
+ const Expr *Lower = ASecE->getLowerBound();
+ Expr::EvalResult Result;
+ if (Lower->EvaluateAsInt(Result, CGF.getContext())) {
+ llvm::APSInt ConstLow = Result.Val.getInt();
+ if (ConstLow == 0) {
+ CheckLength = true;
+ }
+ }
+ }
+ if (CheckLength) {
+ if (ArrayBase->getType()->isArrayType() &&
+ !ASecE->getLength()) {
+ MapExpr = ArrayBase;
+ } else if (ASecE->getLength()) {
+ const Expr *Upper = ASecE->getLength();
+ Expr::EvalResult Result;
+ if (Upper->EvaluateAsInt(Result, CGF.getContext())) {
+ llvm::APSInt ConstLength = Result.Val.getInt();
+ if (ConstLength != 0) {
+ MapExpr = ArrayBase;
+ }
+ }
+ }
+ }
+ }
+ if (MapExpr == MapExprOrig && MapExpr->getType()->isPointerType()) {
+ // It's just a base pointer, ignore it here.
+ continue;
+ }
+ bool Indirect = MapExpr->getType()->isPointerType();
+ // The only things used as keys in PartialStructs are known to be used
+ // as the base expressions of MemberExprs, so this is safer than it looks.
+ EffectiveBaseMapKey EBKey(CGF.getContext(), MapExpr, Indirect);
+ if (PartialStructs.find(EBKey) != PartialStructs.end()) {
+ StructRangeInfoTy *PartialStruct = &PartialStructs[EBKey];
+ fprintf(stderr, "Mapped whole of struct, marking: ");
+ MapExprOrig->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ PartialStruct->ContainingStructMap = &L;
+ QualType Ty = PartialStruct->BaseExpr->getType().getCanonicalType();
+ fprintf(stderr, "BaseExpr Type:\n");
+ Ty.dump();
+ //if (PartialStruct->MemberDepth > 1) {
+ // PartialStruct->LB =
+ // CGF.EmitLoadOfPointer(PartialStruct->Base, Ty->castAs<PointerType>());
+ //} else {
+ // The first one is indirected already.
+ PartialStruct->LB = CGF.EmitLoadOfPointer(PartialStruct->BaseAddr, Ty->castAs<PointerType>());
+ ProcessedMappings.insert(&L);
+ //} else {
+ // }
+ }
+ }
+
+ fprintf(stderr, "Sorting partial structs, pass 3:\n");
+ for (auto &PS : PartialStructs) {
+ auto &PartialStruct = PS.getSecond();
+
+ llvm::DenseMap<const FieldDecl *, uint64_t> Layout;
+
+ const Type *BaseType = PartialStruct.BaseExpr->getType().getCanonicalType().getTypePtr();
+ const Type *OrigType = BaseType->getPointeeOrArrayElementType();
+
+ while (BaseType != OrigType) {
+ BaseType = OrigType->getCanonicalTypeInternal().getTypePtr();
+ OrigType = BaseType->getPointeeOrArrayElementType();
+ }
+
+ if (const auto *CRD = BaseType->getAsCXXRecordDecl()) {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> Processed;
+ getFieldOffsets(CRD, Layout, Processed, 0, /*AsBase=*/false);
+ } else {
+ assert(false && "Not CXX record decl");
+ }
+
+ llvm::stable_sort(PartialStruct.ChildComponents,
+ [this, &Layout](auto &a, auto &b) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef First = a.second.Components;
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Second = b.second.Components;
+
+ auto CI = First.begin();
+ auto CE = First.end();
+ auto SI = Second.begin();
+ auto SE = Second.end();
+
+ // We may have a member expression, or an ArraySectionExpr. Find the
+ // outermost member expression.
+ while (CI != CE) {
+ if (isa<MemberExpr>(CI->getAssociatedExpression()))
+ break;
+ else
+ ++CI;
+ }
+
+ if (CI == CE)
+ return false;
+
+ while (SI != SE) {
+ if (isa<MemberExpr>(SI->getAssociatedExpression()))
+ break;
+ else
+ ++SI;
+ }
+
+ if (SI == SE)
+ return false;
+
+ fprintf(stderr, "Compare CI expr: ");
+ CI->getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\nwith SI expr: ");
+ SI->getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+
+ const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
+ const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
+
+ /*while (auto *ME = dyn_cast<MemberExpr>(CI->getAssociatedExpression())) {
+ if (ME->isArrow())
+ break;
+ auto *Next = std::next(CI);
+ if (Next == CE)
+ break;
+ if (isa<MemberExpr>(Next->getAssociatedExpression()))
+ ++CI;
+ else
+ break;
+ }
+
+ while (auto *ME = dyn_cast<MemberExpr>(SI->getAssociatedExpression())) {
+ if (ME->isArrow())
+ break;
+ auto *Next = std::next(SI);
+ if (Next == SE)
+ break;
+ if (isa<MemberExpr>(Next->getAssociatedExpression()))
+ ++SI;
+ else
+ break;
+ }
+
+ const RecordDecl *RD = FD1->getParent();
+ const RecordDecl *RD2 = FD2->getParent();
+
+ assert(RD == RD2 && "expected the same record decl");
+
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);*/
+ uint64_t FieldOffset1 = Layout[FD1];
+ uint64_t FieldOffset2 = Layout[FD2];
+
+ fprintf(stderr, "Field offset 1: %llu\n", (unsigned long long) FieldOffset1);
+ fprintf(stderr, "Field offset 2: %llu\n", (unsigned long long) FieldOffset2);
+
+ return FieldOffset2 > FieldOffset1;
+ });
+ }
+
+ // FIXME
+ bool IsNonContiguous = false;
+ int DimSize = 1;
+
+ std::vector<EffectiveBaseMapKey> StructOrder;
+
+ for (auto &PS : PartialStructs) {
+ StructOrder.push_back(PS.getFirst());
+ }
+
+ llvm::stable_sort(StructOrder, [&PartialStructs](auto First, auto Second) {
+ auto FirstInfo = PartialStructs[First];
+ auto SecondInfo = PartialStructs[Second];
+ return FirstInfo.MemberDepth < SecondInfo.MemberDepth;
+ });
+
+ auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
+ const MemberExpr *E) {
+ const Expr *BaseExpr = E->getBase();
+ // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a
+ // scalar.
+ LValue BaseLV;
+ if (E->isArrow()) {
+ LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
+ Address Addr =
+ CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo);
+ QualType PtrTy = BaseExpr->getType()->getPointeeType();
+ BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo);
+ } else {
+ BaseLV = CGF.EmitOMPSharedLValue(BaseExpr);
+ }
+ return BaseLV;
+ };
+
+ bool ParamFlag = true;
+
+ fprintf(stderr, "Emit partial struct nodes, pass 4:\n");
+ for (auto &Ord : StructOrder) {
+ auto &PartialStruct = PartialStructs[Ord];
+ MapCombinedInfoTy CombinedInfo;
+
+ fprintf(stderr, "A partial struct (depth %d):\n", PartialStruct.MemberDepth);
+ if (PartialStruct.Base.isValid()) {
+ llvm::dbgs() << "Base expr: ";
+ PartialStruct.BaseExpr->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ llvm::dbgs() << "Name: " << PartialStruct.Base.getName() << "\n";
+ llvm::dbgs() << "Is valid: " << (PartialStruct.Base.isValid() ? "true" : "false") << "\n";
+ } else {
+ llvm::dbgs() << "(no base set)\n";
+ }
+ llvm::dbgs() << "Lo elem: " << PartialStruct.LowestElem.first << "\n";
+ llvm::dbgs() << "Hi elem: " << PartialStruct.HighestElem.first << "\n";
+ //CombinedInfo.append(PartialStruct.PreliminaryMapData);
+ fprintf(stderr, "Child components:\n");
+ for (auto &CC : PartialStruct.ChildComponents) {
+ auto Comp = CC.second.Components;
+ Comp[0].getAssociatedExpression()->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, "Map whole struct: %s\n", PartialStruct.ContainingStructMap ? "yes" : "no");
+
+ if (PartialStruct.ContainingStructMap) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ const ValueDecl *Mapper;
+ const Expr *MapExpr;
+ std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, MapExpr) =
+ *PartialStruct.ContainingStructMap;
+ const Type *BaseType = PartialStruct.BaseExpr->getType().getCanonicalType().getTypePtr();
+ const Type *OrigType = BaseType->getPointeeOrArrayElementType();
+
+ while (BaseType != OrigType) {
+ BaseType = OrigType->getCanonicalTypeInternal().getTypePtr();
+ OrigType = BaseType->getPointeeOrArrayElementType();
+ }
+
+ fprintf(stderr, "Base expr type:\n");
+ BaseType->dump();
+
+ CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(BaseType);
+ Address HB = CGF.Builder.CreateConstGEP(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PartialStruct.Base, CGF.VoidPtrTy, CGF.Int8Ty),
+ TypeSize.getQuantity() - 1);
+ PartialStruct.HighestElem = {
+ std::numeric_limits<decltype(
+ PartialStruct.HighestElem.first)>::max(),
+ HB};
+ OpenMPOffloadMappingFlags Flags =
+ OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
+ getMapTypeBits(MapType, MapModifiers, {}, IsImplicit,
+ /*AddPtrFlag=*/false,
+ /*AddIsTargetParamFlag=*/false, IsNonContiguous);
+ fprintf(stderr, "Starting CopyGaps...\n");
+ CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, nullptr,
+ PartialStruct.BaseExpr, PartialStruct.Base,
+ PartialStruct.LB, IsNonContiguous, DimSize);
+
+ llvm::DenseMap<const FieldDecl *, uint64_t> Layout;
+
+ if (const auto *CRD = BaseType->getAsCXXRecordDecl()) {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 4> Processed;
+ getFieldOffsets(CRD, Layout, Processed, 0, /*AsBase=*/false);
+ } else {
+ assert(false && "Not CXX record decl");
+ }
+
+ for (auto &CC : PartialStruct.ChildComponents) {
+ const OMPClauseMappableExprCommon::MappableComponent &MC = CC.second.Components.front();
+ if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
+ if (const auto *FD = dyn_cast<FieldDecl>(VD)) {
+ CopyGaps.processField(MC, Layout, FD, EmitMemberExprBase);
+ }
+ }
+ }
+ CopyGaps.copyUntilEnd(HB, TypeSize);
+ }
+
+ for (auto &CC : PartialStruct.ChildComponents) {
+ MappableExprMetadata Metadata = CC.second;
+ auto Field = Metadata.Components.front().getAssociatedExpression();
+ // Address Ptr = CGF.EmitOMPSharedLValue(Field).getAddress();
+ llvm::Value *Size = getExprTypeSize(Field);
+
+ fprintf(stderr, "Emitting expr: ");
+ Field->dumpPretty(CGF.getContext());
+ fprintf(stderr, "\n");
+
+ if (Metadata.CompleteExpression || PartialStruct.ContainingStructMap) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
+ OpenMPMapClauseKind MapType;
+ ArrayRef<OpenMPMapModifierKind> MapModifiers;
+ bool IsImplicit;
+ const ValueDecl *Mapper;
+ const Expr *MapExpr;
+ //if (PartialStruct.ContainingStructMap) {
+ // std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, MapExpr) =
+ // *PartialStruct.ContainingStructMap;
+ //} else {
+ std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, MapExpr) =
+ *Metadata.MD;
+ //}
+
+ CombinedInfo.Exprs.push_back(nullptr);
+ CombinedInfo.BasePointers.push_back(Metadata.Base.emitRawPointer(CGF));
+ CombinedInfo.DevicePtrDecls.push_back(nullptr);
+ CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+ CombinedInfo.Pointers.push_back(Metadata.Pointer.emitRawPointer(CGF));
+ CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
+ Size, CGF.Int64Ty, /*isSigned=*/true));
+ CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
+ CombinedInfo.Mappers.push_back(nullptr);
+
+ bool PointerAndObj = false;
+ if (isa<ArraySectionExpr>(Field) ||
+ isa<ArraySubscriptExpr>(Field) ||
+ isa<OMPArrayShapingExpr>(Field) ||
+ isa<UnaryOperator>(Field))
+ PointerAndObj = true;
+
+ OpenMPOffloadMappingFlags Flags =
+ getMapTypeBits(MapType, MapModifiers, {}, IsImplicit, PointerAndObj, false, IsNonContiguous);
+ Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
+
+ CombinedInfo.Types.push_back(Flags);
+
+ fprintf(stderr, "Marking %p as processed\n", (void*) Metadata.MD);
+ ProcessedMappings.insert(Metadata.MD);
+ }
+ }
+
+ if (ParamFlag || !PartialStruct.ContainingStructMap) {
+ OpenMPOffloadMappingFlags Flags = ParamFlag ? OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM
+ : OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
+ emitCombinedEntry(CurComponentListInfo, CombinedInfo.Types, PartialStruct,
+ false, OMPBuilder, VD, 0, Flags);
+ } else {
+ OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
+ CurComponentListInfo.BasePointers.size() - 1);
+ for (auto &M : CombinedInfo.Types)
+ OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
+ }
+
+ CurComponentListInfo.append(CombinedInfo);
+ ParamFlag = false;
+ }
+ fprintf(stderr, "That's all\n");
+
+ #if 0
// Associated with a capture, because the mapping flags depend on it.
// Go through all of the elements with the overlapped elements.
bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
- MapCombinedInfoTy StructBaseCombinedInfo;
+ //MapCombinedInfoTy StructBaseCombinedInfo;
for (const auto &Pair : OverlappedData) {
const MapData &L = *Pair.getFirst();
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
@@ -8999,15 +10091,26 @@ class MappableExprsHandler {
L;
ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
OverlappedComponents = Pair.getSecond();
+ fprintf(stderr, "*** From generateInfoForCaptureFromComponentLists (overlapped)...\n");
generateInfoForComponentList(
MapType, MapModifiers, {}, Components, CurComponentListInfo,
- StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag, IsImplicit,
- /*GenerateAllInfoForClauses*/ false, Mapper,
+ PartialStructs, AddTargetParamFlag, IsImplicit, Mapper,
/*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents);
AddTargetParamFlag = false;
}
+ #endif
+
+ // FIXME: Check this.
+ bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
+
// Go through other elements without overlapped elements.
for (const MapData &L : DeclComponentLists) {
+ if (ProcessedMappings.contains(&L)) {
+ fprintf(stderr, "Already processed map data for %p, skipping\n",
+ (void*) &L);
+ continue;
+ }
+
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
OpenMPMapClauseKind MapType;
ArrayRef<OpenMPMapModifierKind> MapModifiers;
@@ -9016,14 +10119,17 @@ class MappableExprsHandler {
const Expr *VarRef;
std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
L;
- auto It = OverlappedData.find(&L);
- if (It == OverlappedData.end())
+ //auto It = OverlappedData.find(&L);
+ //if (It == OverlappedData.end()) {
+ fprintf(stderr, "*** From generateInfoForCaptureFromComponentLists (non-overlapped)...\n");
+#if 1
generateInfoForComponentList(
MapType, MapModifiers, {}, Components, CurComponentListInfo,
- StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag,
- IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper,
+ PartialStructs, AddTargetParamFlag, IsImplicit, Mapper,
/*ForDeviceAddr=*/false, VD, VarRef,
- /*OverlappedElements*/ {}, AreBothBasePtrAndPteeMapped);
+ /*OverlappedElements {},*/ AreBothBasePtrAndPteeMapped);
+#endif
+ //}
AddTargetParamFlag = false;
}
}
@@ -9110,6 +10216,7 @@ class MappableExprsHandler {
CombinedInfo.Mappers.push_back(nullptr);
}
};
+
} // anonymous namespace
// Try to extract the base declaration from a `this->x` expression if possible.
@@ -9496,6 +10603,8 @@ static void genMapInfoForCaptures(
llvm::DenseSet<CanonicalDeclPtr<const Decl>> &MappedVarSet,
MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
+ fprintf(stderr, "genMapInfoForCaptures\n");
+
llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
auto RI = CS.getCapturedRecordDecl()->field_begin();
auto *CV = CapturedVars.begin();
@@ -9503,6 +10612,18 @@ static void genMapInfoForCaptures(
CE = CS.capture_end();
CI != CE; ++CI, ++RI, ++CV) {
MappableExprsHandler::MapCombinedInfoTy CurInfo;
+ MappableExprsHandler::PartialStructMap PartialStructs;
+
+ auto V = CI->getCapturedVar();
+ llvm::dbgs() << "var:\n";
+ V->dump();
+ llvm::dbgs() << "\ncaptured by:\n";
+ switch (CI->getCaptureKind()) {
+ case CapturedStmt::VCK_This: llvm::dbgs() << "this\n"; break;
+ case CapturedStmt::VCK_ByRef: llvm::dbgs() << "byref\n"; break;
+ case CapturedStmt::VCK_ByCopy: llvm::dbgs() << "bycopy\n"; break;
+ case CapturedStmt::VCK_VLAType: llvm::dbgs() << "vlatype\n"; break;
+ }
// VLA sizes are passed to the outlined region by copy and do not have map
// information associated.
@@ -9524,15 +10645,14 @@ static void genMapInfoForCaptures(
// If we have any information in the map clause, we use it, otherwise we
// just do a default mapping.
MEHandler.generateInfoForCaptureFromClauseInfo(
- CI, *CV, CurInfo, OMPBuilder,
+ CI, *CV, CurInfo, PartialStructs, OMPBuilder,
/*OffsetForMemberOfFlag=*/CombinedInfo.BasePointers.size());
if (!CI->capturesThis())
MappedVarSet.insert(CI->getCapturedVar());
else
MappedVarSet.insert(nullptr);
-
- if (CurInfo.BasePointers.empty())
+ if (CurInfo.BasePointers.empty() && PartialStructs.empty())
MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
// Generate correct mapping for variables captured by reference in
@@ -9550,6 +10670,32 @@ static void genMapInfoForCaptures(
CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
"Inconsistent map information sizes!");
+ // If there is an entry in PartialStruct it means we have a struct with
+ // individual members mapped. Emit an extra combined entry. FIXME.
+ //if (PartialStruct.Base.isValid()) {
+ // CombinedInfo.append(PartialStruct.PreliminaryMapData);
+ // MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
+ // CI->capturesThis(), OMPBuilder, nullptr,
+ // /*NotTargetParams*/ false);
+ //}
+
+#if 0
+ fprintf(stderr, "Gathered up partial structs (2):\n");
+ for (auto &PS : PartialStructs) {
+ auto &PartialStruct = PS.getSecond();
+ fprintf(stderr, "A partial struct:\n");
+ llvm::dbgs() << "Name: " << PartialStruct.Base.getName() << "\n";
+ llvm::dbgs() << "Is valid: " << (PartialStruct.Base.isValid() ? "true" : "false") << "\n";
+ llvm::dbgs() << "Lo elem: " << PartialStruct.LowestElem.first << "\n";
+ llvm::dbgs() << "Hi elem: " << PartialStruct.HighestElem.first << "\n";
+ //CombinedInfo.append(PartialStruct.PreliminaryMapData);
+ //MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
+ // CI->capturesThis(), OMPBuilder, nullptr,
+ // /*NotTargetParams*/ false);
+ }
+#endif
+ fprintf(stderr, "That's all\n");
+
// We need to append the results of this capture to what we already have.
CombinedInfo.append(CurInfo);
}
More information about the cfe-commits
mailing list