Refactor OpenMP stack management.

Instead of duplicating access to the directive stack throughout
SemaOpenMP.cpp, consolidate it to a few methods and call those
everywhere else. In passing, simplify adjacent code where possible.

No functionality change intended.

llvm-svn: 362172
This commit is contained in:
Richard Smith 2019-05-30 23:21:14 +00:00
parent 073f3f1609
commit 375dec5e45
1 changed files with 224 additions and 214 deletions

View File

@ -173,18 +173,78 @@ private:
bool ForceCaptureByReferenceInTargetExecutable = false;
CriticalsWithHintsTy Criticals;
using iterator = StackTy::const_reverse_iterator;
/// Iterators over the stack iterate in order from innermost to outermost
/// directive.
using const_iterator = StackTy::const_reverse_iterator;
const_iterator begin() const {
return Stack.empty() ? const_iterator() : Stack.back().first.rbegin();
}
const_iterator end() const {
return Stack.empty() ? const_iterator() : Stack.back().first.rend();
}
using iterator = StackTy::reverse_iterator;
iterator begin() {
return Stack.empty() ? iterator() : Stack.back().first.rbegin();
}
iterator end() {
return Stack.empty() ? iterator() : Stack.back().first.rend();
}
DSAVarData getDSA(iterator &Iter, ValueDecl *D) const;
/// Checks if the variable is a local for OpenMP region.
bool isOpenMPLocal(VarDecl *D, iterator Iter) const;
// Convenience operations to get at the elements of the stack.
bool isStackEmpty() const {
return Stack.empty() ||
Stack.back().second != CurrentNonCapturingFunctionScope ||
Stack.back().first.empty();
}
size_t getStackSize() const {
return isStackEmpty() ? 0 : Stack.back().first.size();
}
SharingMapTy *getTopOfStackOrNull() {
if (isStackEmpty())
return nullptr;
return &Stack.back().first.back();
}
const SharingMapTy *getTopOfStackOrNull() const {
return const_cast<DSAStackTy&>(*this).getTopOfStackOrNull();
}
SharingMapTy &getTopOfStack() {
assert(!isStackEmpty() && "no current directive");
return *getTopOfStackOrNull();
}
const SharingMapTy &getTopOfStack() const {
return const_cast<DSAStackTy&>(*this).getTopOfStack();
}
SharingMapTy *getSecondOnStackOrNull() {
size_t Size = getStackSize();
if (Size <= 1)
return nullptr;
return &Stack.back().first[Size - 2];
}
const SharingMapTy *getSecondOnStackOrNull() const {
return const_cast<DSAStackTy&>(*this).getSecondOnStackOrNull();
}
/// Get the stack element at a certain level (previously returned by
/// \c getNestingLevel).
///
/// Note that nesting levels count from outermost to innermost, and this is
/// the reverse of our iteration order where new inner levels are pushed at
/// the front of the stack.
SharingMapTy &getStackElemAtLevel(unsigned Level) {
assert(Level < getStackSize() && "no such stack element");
return Stack.back().first[Level];
}
const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
return const_cast<DSAStackTy&>(*this).getStackElemAtLevel(Level);
}
DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
/// Checks if the variable is a local for OpenMP region.
bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
/// Vector of previously declared requires directives
SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
@ -249,28 +309,28 @@ public:
void loopInit() {
assert(isOpenMPLoopDirective(getCurrentDirective()) &&
"Expected loop-based directive.");
Stack.back().first.back().LoopStart = true;
getTopOfStack().LoopStart = true;
}
/// Start capturing of the variables in the loop context.
void loopStart() {
assert(isOpenMPLoopDirective(getCurrentDirective()) &&
"Expected loop-based directive.");
Stack.back().first.back().LoopStart = false;
getTopOfStack().LoopStart = false;
}
/// true, if variables are captured, false otherwise.
bool isLoopStarted() const {
assert(isOpenMPLoopDirective(getCurrentDirective()) &&
"Expected loop-based directive.");
return !Stack.back().first.back().LoopStart;
return !getTopOfStack().LoopStart;
}
/// Marks (or clears) declaration as possibly loop counter.
void resetPossibleLoopCounter(const Decl *D = nullptr) {
Stack.back().first.back().PossiblyLoopCounter =
getTopOfStack().PossiblyLoopCounter =
D ? D->getCanonicalDecl() : D;
}
/// Gets the possible loop counter decl.
const Decl *getPossiblyLoopCunter() const {
return Stack.back().first.back().PossiblyLoopCounter;
return getTopOfStack().PossiblyLoopCounter;
}
/// Start new OpenMP region stack in new non-capturing function.
void pushFunction() {
@ -350,16 +410,16 @@ public:
Expr *&TaskgroupDescriptor) const;
/// Return reduction reference expression for the current taskgroup.
Expr *getTaskgroupReductionRef() const {
assert(Stack.back().first.back().Directive == OMPD_taskgroup &&
assert(getTopOfStack().Directive == OMPD_taskgroup &&
"taskgroup reference expression requested for non taskgroup "
"directive.");
return Stack.back().first.back().TaskgroupReductionRef;
return getTopOfStack().TaskgroupReductionRef;
}
/// Checks if the given \p VD declaration is actually a taskgroup reduction
/// descriptor variable at the \p Level of OpenMP regions.
bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
return Stack.back().first[Level].TaskgroupReductionRef &&
cast<DeclRefExpr>(Stack.back().first[Level].TaskgroupReductionRef)
return getStackElemAtLevel(Level).TaskgroupReductionRef &&
cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
->getDecl() == VD;
}
@ -405,18 +465,18 @@ public:
/// Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return isStackEmpty() ? OMPD_unknown : Stack.back().first.back().Directive;
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->Directive : OMPD_unknown;
}
/// Returns directive kind at specified level.
OpenMPDirectiveKind getDirective(unsigned Level) const {
assert(!isStackEmpty() && "No directive at specified level.");
return Stack.back().first[Level].Directive;
return getStackElemAtLevel(Level).Directive;
}
/// Returns parent directive.
OpenMPDirectiveKind getParentDirective() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return OMPD_unknown;
return std::next(Stack.back().first.rbegin())->Directive;
const SharingMapTy *Parent = getSecondOnStackOrNull();
return Parent ? Parent->Directive : OMPD_unknown;
}
/// Add requires decl to internal vector
@ -468,41 +528,38 @@ public:
/// Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultAttr = DSA_none;
Stack.back().first.back().DefaultAttrLoc = Loc;
getTopOfStack().DefaultAttr = DSA_none;
getTopOfStack().DefaultAttrLoc = Loc;
}
/// Set default data sharing attribute to shared.
void setDefaultDSAShared(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultAttr = DSA_shared;
Stack.back().first.back().DefaultAttrLoc = Loc;
getTopOfStack().DefaultAttr = DSA_shared;
getTopOfStack().DefaultAttrLoc = Loc;
}
/// Set default data mapping attribute to 'tofrom:scalar'.
void setDefaultDMAToFromScalar(SourceLocation Loc) {
assert(!isStackEmpty());
Stack.back().first.back().DefaultMapAttr = DMA_tofrom_scalar;
Stack.back().first.back().DefaultMapAttrLoc = Loc;
getTopOfStack().DefaultMapAttr = DMA_tofrom_scalar;
getTopOfStack().DefaultMapAttrLoc = Loc;
}
DefaultDataSharingAttributes getDefaultDSA() const {
return isStackEmpty() ? DSA_unspecified
: Stack.back().first.back().DefaultAttr;
: getTopOfStack().DefaultAttr;
}
SourceLocation getDefaultDSALocation() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().DefaultAttrLoc;
: getTopOfStack().DefaultAttrLoc;
}
DefaultMapAttributes getDefaultDMA() const {
return isStackEmpty() ? DMA_unspecified
: Stack.back().first.back().DefaultMapAttr;
: getTopOfStack().DefaultMapAttr;
}
DefaultMapAttributes getDefaultDMAAtLevel(unsigned Level) const {
return Stack.back().first[Level].DefaultMapAttr;
return getStackElemAtLevel(Level).DefaultMapAttr;
}
SourceLocation getDefaultDMALocation() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().DefaultMapAttrLoc;
: getTopOfStack().DefaultMapAttrLoc;
}
/// Checks if the specified variable is a threadprivate.
@ -514,82 +571,77 @@ public:
/// Marks current region as ordered (it has an 'ordered' clause).
void setOrderedRegion(bool IsOrdered, const Expr *Param,
OMPOrderedClause *Clause) {
assert(!isStackEmpty());
if (IsOrdered)
Stack.back().first.back().OrderedRegion.emplace(Param, Clause);
getTopOfStack().OrderedRegion.emplace(Param, Clause);
else
Stack.back().first.back().OrderedRegion.reset();
getTopOfStack().OrderedRegion.reset();
}
/// Returns true, if region is ordered (has associated 'ordered' clause),
/// false - otherwise.
bool isOrderedRegion() const {
if (isStackEmpty())
return false;
return Stack.back().first.rbegin()->OrderedRegion.hasValue();
if (const SharingMapTy *Top = getTopOfStackOrNull())
return Top->OrderedRegion.hasValue();
return false;
}
/// Returns optional parameter for the ordered region.
std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
if (isStackEmpty() ||
!Stack.back().first.rbegin()->OrderedRegion.hasValue())
return std::make_pair(nullptr, nullptr);
return Stack.back().first.rbegin()->OrderedRegion.getValue();
if (const SharingMapTy *Top = getTopOfStackOrNull())
if (Top->OrderedRegion.hasValue())
return Top->OrderedRegion.getValue();
return std::make_pair(nullptr, nullptr);
}
/// Returns true, if parent region is ordered (has associated
/// 'ordered' clause), false - otherwise.
bool isParentOrderedRegion() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return false;
return std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue();
if (const SharingMapTy *Parent = getSecondOnStackOrNull())
return Parent->OrderedRegion.hasValue();
return false;
}
/// Returns optional parameter for the ordered region.
std::pair<const Expr *, OMPOrderedClause *>
getParentOrderedRegionParam() const {
if (isStackEmpty() || Stack.back().first.size() == 1 ||
!std::next(Stack.back().first.rbegin())->OrderedRegion.hasValue())
return std::make_pair(nullptr, nullptr);
return std::next(Stack.back().first.rbegin())->OrderedRegion.getValue();
if (const SharingMapTy *Parent = getSecondOnStackOrNull())
if (Parent->OrderedRegion.hasValue())
return Parent->OrderedRegion.getValue();
return std::make_pair(nullptr, nullptr);
}
/// Marks current region as nowait (it has a 'nowait' clause).
void setNowaitRegion(bool IsNowait = true) {
assert(!isStackEmpty());
Stack.back().first.back().NowaitRegion = IsNowait;
getTopOfStack().NowaitRegion = IsNowait;
}
/// Returns true, if parent region is nowait (has associated
/// 'nowait' clause), false - otherwise.
bool isParentNowaitRegion() const {
if (isStackEmpty() || Stack.back().first.size() == 1)
return false;
return std::next(Stack.back().first.rbegin())->NowaitRegion;
if (const SharingMapTy *Parent = getSecondOnStackOrNull())
return Parent->NowaitRegion;
return false;
}
/// Marks parent region as cancel region.
void setParentCancelRegion(bool Cancel = true) {
if (!isStackEmpty() && Stack.back().first.size() > 1) {
auto &StackElemRef = *std::next(Stack.back().first.rbegin());
StackElemRef.CancelRegion |= StackElemRef.CancelRegion || Cancel;
}
if (SharingMapTy *Parent = getSecondOnStackOrNull())
Parent->CancelRegion |= Cancel;
}
/// Return true if current region has inner cancel construct.
bool isCancelRegion() const {
return isStackEmpty() ? false : Stack.back().first.back().CancelRegion;
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->CancelRegion : false;
}
/// Set collapse value for the region.
void setAssociatedLoops(unsigned Val) {
assert(!isStackEmpty());
Stack.back().first.back().AssociatedLoops = Val;
getTopOfStack().AssociatedLoops = Val;
}
/// Return collapse value for region.
unsigned getAssociatedLoops() const {
return isStackEmpty() ? 0 : Stack.back().first.back().AssociatedLoops;
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->AssociatedLoops : 0;
}
/// Marks current target region as one with closely nested teams
/// region.
void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
if (!isStackEmpty() && Stack.back().first.size() > 1) {
std::next(Stack.back().first.rbegin())->InnerTeamsRegionLoc =
TeamsRegionLoc;
}
if (SharingMapTy *Parent = getSecondOnStackOrNull())
Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
}
/// Returns true, if current region has closely nested teams region.
bool hasInnerTeamsRegion() const {
@ -597,16 +649,17 @@ public:
}
/// Returns location of the nested teams region (if any).
SourceLocation getInnerTeamsRegionLoc() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().InnerTeamsRegionLoc;
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
}
Scope *getCurScope() const {
return isStackEmpty() ? nullptr : Stack.back().first.back().CurScope;
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->CurScope : nullptr;
}
SourceLocation getConstructLoc() const {
return isStackEmpty() ? SourceLocation()
: Stack.back().first.back().ConstructLoc;
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->ConstructLoc : SourceLocation();
}
/// Do the check specified in \a Check to all component lists and return true
@ -619,8 +672,8 @@ public:
Check) const {
if (isStackEmpty())
return false;
auto SI = Stack.back().first.rbegin();
auto SE = Stack.back().first.rend();
auto SI = begin();
auto SE = end();
if (SI == SE)
return false;
@ -649,17 +702,12 @@ public:
bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
OpenMPClauseKind)>
Check) const {
if (isStackEmpty())
if (getStackSize() <= Level)
return false;
auto StartI = Stack.back().first.begin();
auto EndI = Stack.back().first.end();
if (std::distance(StartI, EndI) <= (int)Level)
return false;
std::advance(StartI, Level);
auto MI = StartI->MappedExprComponents.find(VD);
if (MI != StartI->MappedExprComponents.end())
const SharingMapTy &StackElem = getStackElemAtLevel(Level);
auto MI = StackElem.MappedExprComponents.find(VD);
if (MI != StackElem.MappedExprComponents.end())
for (OMPClauseMappableExprCommon::MappableExprComponentListRef L :
MI->second.Components)
if (Check(L, MI->second.Kind))
@ -673,10 +721,7 @@ public:
const ValueDecl *VD,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPClauseKind WhereFoundClauseKind) {
assert(!isStackEmpty() &&
"Not expecting to retrieve components from a empty stack!");
MappedExprComponentTy &MEC =
Stack.back().first.back().MappedExprComponents[VD];
MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
// Create new entry and append the new components there.
MEC.Components.resize(MEC.Components.size() + 1);
MEC.Components.back().append(Components.begin(), Components.end());
@ -685,19 +730,17 @@ public:
unsigned getNestingLevel() const {
assert(!isStackEmpty());
return Stack.back().first.size() - 1;
return getStackSize() - 1;
}
void addDoacrossDependClause(OMPDependClause *C,
const OperatorOffsetTy &OpsOffs) {
assert(!isStackEmpty() && Stack.back().first.size() > 1);
SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
assert(isOpenMPWorksharingDirective(StackElem.Directive));
StackElem.DoacrossDepends.try_emplace(C, OpsOffs);
SharingMapTy *Parent = getSecondOnStackOrNull();
assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
Parent->DoacrossDepends.try_emplace(C, OpsOffs);
}
llvm::iterator_range<DoacrossDependMapTy::const_iterator>
getDoacrossDependClauses() const {
assert(!isStackEmpty());
const SharingMapTy &StackElem = Stack.back().first.back();
const SharingMapTy &StackElem = getTopOfStack();
if (isOpenMPWorksharingDirective(StackElem.Directive)) {
const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
return llvm::make_range(Ref.begin(), Ref.end());
@ -708,13 +751,13 @@ public:
// Store types of classes which have been explicitly mapped
void addMappedClassesQualTypes(QualType QT) {
SharingMapTy &StackElem = Stack.back().first.back();
SharingMapTy &StackElem = getTopOfStack();
StackElem.MappedClassesQualTypes.insert(QT);
}
// Return set of mapped classes types
bool isClassPreviouslyMapped(QualType QT) const {
const SharingMapTy &StackElem = Stack.back().first.back();
const SharingMapTy &StackElem = getTopOfStack();
return StackElem.MappedClassesQualTypes.count(QT) != 0;
}
@ -723,16 +766,11 @@ public:
assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
"Expected declare target link global.");
if (isStackEmpty())
return;
auto It = Stack.back().first.rbegin();
while (It != Stack.back().first.rend() &&
!isOpenMPTargetExecutionDirective(It->Directive))
++It;
if (It != Stack.back().first.rend()) {
assert(isOpenMPTargetExecutionDirective(It->Directive) &&
"Expected target executable directive.");
It->DeclareTargetLinkVarDecls.push_back(E);
for (auto &Elem : *this) {
if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
Elem.DeclareTargetLinkVarDecls.push_back(E);
return;
}
}
}
@ -741,7 +779,7 @@ public:
ArrayRef<DeclRefExpr *> getLinkGlobals() const {
assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
"Expected target executable directive.");
return Stack.back().first.back().DeclareTargetLinkVarDecls;
return getTopOfStack().DeclareTargetLinkVarDecls;
}
};
@ -797,13 +835,13 @@ static ValueDecl *getCanonicalDecl(ValueDecl *D) {
getCanonicalDecl(const_cast<const ValueDecl *>(D)));
}
DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter,
DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
ValueDecl *D) const {
D = getCanonicalDecl(D);
auto *VD = dyn_cast<VarDecl>(D);
const auto *FD = dyn_cast<FieldDecl>(D);
DSAVarData DVar;
if (isStackEmpty() || Iter == Stack.back().first.rend()) {
if (Iter == end()) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a region but not in construct]
// File-scope or namespace-scope variables referenced in called routines
@ -878,7 +916,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter,
// bound to the current team is shared.
if (isOpenMPTaskingDirective(DVar.DKind)) {
DSAVarData DVarTemp;
iterator I = Iter, E = Stack.back().first.rend();
const_iterator I = Iter, E = end();
do {
++I;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
@ -910,7 +948,7 @@ const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
const Expr *NewDE) {
assert(!isStackEmpty() && "Data sharing attributes stack is empty");
D = getCanonicalDecl(D);
SharingMapTy &StackElem = Stack.back().first.back();
SharingMapTy &StackElem = getTopOfStack();
auto It = StackElem.AlignedMap.find(D);
if (It == StackElem.AlignedMap.end()) {
assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
@ -924,7 +962,7 @@ const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
SharingMapTy &StackElem = Stack.back().first.back();
SharingMapTy &StackElem = getTopOfStack();
StackElem.LCVMap.try_emplace(
D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
}
@ -933,7 +971,7 @@ const DSAStackTy::LCDeclInfo
DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
const SharingMapTy &StackElem = Stack.back().first.back();
const SharingMapTy &StackElem = getTopOfStack();
auto It = StackElem.LCVMap.find(D);
if (It != StackElem.LCVMap.end())
return It->second;
@ -942,23 +980,21 @@ DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
const DSAStackTy::LCDeclInfo
DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
"Data-sharing attributes stack is empty");
const SharingMapTy *Parent = getSecondOnStackOrNull();
assert(Parent && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
const SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
auto It = StackElem.LCVMap.find(D);
if (It != StackElem.LCVMap.end())
auto It = Parent->LCVMap.find(D);
if (It != Parent->LCVMap.end())
return It->second;
return {0, nullptr};
}
const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
"Data-sharing attributes stack is empty");
const SharingMapTy &StackElem = *std::next(Stack.back().first.rbegin());
if (StackElem.LCVMap.size() < I)
const SharingMapTy *Parent = getSecondOnStackOrNull();
assert(Parent && "Data-sharing attributes stack is empty");
if (Parent->LCVMap.size() < I)
return nullptr;
for (const auto &Pair : StackElem.LCVMap)
for (const auto &Pair : Parent->LCVMap)
if (Pair.second.first == I)
return Pair.first;
return nullptr;
@ -973,8 +1009,7 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
Data.RefExpr.setPointer(E);
Data.PrivateCopy = nullptr;
} else {
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
DSAInfo &Data = Stack.back().first.back().SharingMap[D];
DSAInfo &Data = getTopOfStack().SharingMap[D];
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
@ -989,8 +1024,7 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
Data.RefExpr.setPointerAndInt(E, IsLastprivate);
Data.PrivateCopy = PrivateCopy;
if (PrivateCopy) {
DSAInfo &Data =
Stack.back().first.back().SharingMap[PrivateCopy->getDecl()];
DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
Data.Attributes = A;
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
Data.PrivateCopy = nullptr;
@ -1035,16 +1069,16 @@ void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
assert(
Stack.back().first.back().SharingMap[D].Attributes == OMPC_reduction &&
getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
"Additional reduction info may be specified only for reduction items.");
ReductionData &ReductionData = Stack.back().first.back().ReductionMap[D];
ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
assert(ReductionData.ReductionRange.isInvalid() &&
Stack.back().first.back().Directive == OMPD_taskgroup &&
getTopOfStack().Directive == OMPD_taskgroup &&
"Additional reduction info may be specified only once for reduction "
"items.");
ReductionData.set(BOK, SR);
Expr *&TaskgroupReductionRef =
Stack.back().first.back().TaskgroupReductionRef;
getTopOfStack().TaskgroupReductionRef;
if (!TaskgroupReductionRef) {
VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
SemaRef.Context.VoidPtrTy, ".task_red.");
@ -1058,16 +1092,16 @@ void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
assert(
Stack.back().first.back().SharingMap[D].Attributes == OMPC_reduction &&
getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
"Additional reduction info may be specified only for reduction items.");
ReductionData &ReductionData = Stack.back().first.back().ReductionMap[D];
ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
assert(ReductionData.ReductionRange.isInvalid() &&
Stack.back().first.back().Directive == OMPD_taskgroup &&
getTopOfStack().Directive == OMPD_taskgroup &&
"Additional reduction info may be specified only once for reduction "
"items.");
ReductionData.set(ReductionRef, SR);
Expr *&TaskgroupReductionRef =
Stack.back().first.back().TaskgroupReductionRef;
getTopOfStack().TaskgroupReductionRef;
if (!TaskgroupReductionRef) {
VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
SemaRef.Context.VoidPtrTy, ".task_red.");
@ -1081,11 +1115,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
Expr *&TaskgroupDescriptor) const {
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
if (Stack.back().first.empty())
return DSAVarData();
for (iterator I = std::next(Stack.back().first.rbegin(), 1),
E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
const DSAInfo &Data = I->SharingMap.lookup(D);
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
@ -1110,11 +1140,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
Expr *&TaskgroupDescriptor) const {
D = getCanonicalDecl(D);
assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
if (Stack.back().first.empty())
return DSAVarData();
for (iterator I = std::next(Stack.back().first.rbegin(), 1),
E = Stack.back().first.rend();
I != E; std::advance(I, 1)) {
for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
const DSAInfo &Data = I->SharingMap.lookup(D);
if (Data.Attributes != OMPC_reduction || I->Directive != OMPD_taskgroup)
continue;
@ -1134,21 +1160,17 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
return DSAVarData();
}
bool DSAStackTy::isOpenMPLocal(VarDecl *D, iterator Iter) const {
bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
D = D->getCanonicalDecl();
if (!isStackEmpty()) {
iterator I = Iter, E = Stack.back().first.rend();
Scope *TopScope = nullptr;
while (I != E && !isImplicitOrExplicitTaskingRegion(I->Directive) &&
!isOpenMPTargetExecutionDirective(I->Directive))
++I;
if (I == E)
return false;
TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
Scope *CurScope = getCurScope();
while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
CurScope = CurScope->getParent();
return CurScope != TopScope;
for (const_iterator E = end(); I != E; ++I) {
if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
isOpenMPTargetExecutionDirective(I->Directive)) {
Scope *TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
Scope *CurScope = getCurScope();
while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
CurScope = CurScope->getParent();
return CurScope != TopScope;
}
}
return false;
}
@ -1236,15 +1258,14 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
!isLoopControlVariable(D).first) {
iterator IterTarget =
std::find_if(Stack.back().first.rbegin(), Stack.back().first.rend(),
[](const SharingMapTy &Data) {
return isOpenMPTargetExecutionDirective(Data.Directive);
});
if (IterTarget != Stack.back().first.rend()) {
iterator ParentIterTarget = std::next(IterTarget, 1);
for (iterator Iter = Stack.back().first.rbegin();
Iter != ParentIterTarget; std::advance(Iter, 1)) {
const_iterator IterTarget =
std::find_if(begin(), end(), [](const SharingMapTy &Data) {
return isOpenMPTargetExecutionDirective(Data.Directive);
});
if (IterTarget != end()) {
const_iterator ParentIterTarget = IterTarget + 1;
for (const_iterator Iter = begin();
Iter != ParentIterTarget; ++Iter) {
if (isOpenMPLocal(VD, Iter)) {
DVar.RefExpr =
buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
@ -1253,7 +1274,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
return DVar;
}
}
if (!isClauseParsingMode() || IterTarget != Stack.back().first.rbegin()) {
if (!isClauseParsingMode() || IterTarget != begin()) {
auto DSAIter = IterTarget->SharingMap.find(D);
if (DSAIter != IterTarget->SharingMap.end() &&
isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
@ -1261,7 +1282,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
DVar.CKind = OMPC_threadprivate;
return DVar;
}
iterator End = Stack.back().first.rend();
const_iterator End = end();
if (!SemaRef.isOpenMPCapturedByRef(
D, std::distance(ParentIterTarget, End))) {
DVar.RefExpr =
@ -1321,10 +1342,10 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
// Explicitly specified attributes and local variables with predetermined
// attributes.
iterator I = Stack.back().first.rbegin();
iterator EndI = Stack.back().first.rend();
const_iterator I = begin();
const_iterator EndI = end();
if (FromParent && I != EndI)
std::advance(I, 1);
++I;
auto It = I->SharingMap.find(D);
if (It != I->SharingMap.end()) {
const DSAInfo &Data = It->getSecond();
@ -1341,14 +1362,14 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
bool FromParent) const {
if (isStackEmpty()) {
iterator I;
const_iterator I;
return getDSA(I, D);
}
D = getCanonicalDecl(D);
iterator StartI = Stack.back().first.rbegin();
iterator EndI = Stack.back().first.rend();
const_iterator StartI = begin();
const_iterator EndI = end();
if (FromParent && StartI != EndI)
std::advance(StartI, 1);
++StartI;
return getDSA(StartI, D);
}
@ -1360,14 +1381,15 @@ DSAStackTy::hasDSA(ValueDecl *D,
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
iterator I = Stack.back().first.rbegin();
iterator EndI = Stack.back().first.rend();
const_iterator I = begin();
const_iterator EndI = end();
if (FromParent && I != EndI)
std::advance(I, 1);
for (; I != EndI; std::advance(I, 1)) {
if (!DPred(I->Directive) && !isImplicitOrExplicitTaskingRegion(I->Directive))
++I;
for (; I != EndI; ++I) {
if (!DPred(I->Directive) &&
!isImplicitOrExplicitTaskingRegion(I->Directive))
continue;
iterator NewI = I;
const_iterator NewI = I;
DSAVarData DVar = getDSA(NewI, D);
if (I == NewI && CPred(DVar.CKind))
return DVar;
@ -1382,13 +1404,13 @@ const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
if (isStackEmpty())
return {};
D = getCanonicalDecl(D);
iterator StartI = Stack.back().first.rbegin();
iterator EndI = Stack.back().first.rend();
const_iterator StartI = begin();
const_iterator EndI = end();
if (FromParent && StartI != EndI)
std::advance(StartI, 1);
++StartI;
if (StartI == EndI || !DPred(StartI->Directive))
return {};
iterator NewI = StartI;
const_iterator NewI = StartI;
DSAVarData DVar = getDSA(NewI, D);
return (NewI == StartI && CPred(DVar.CKind)) ? DVar : DSAVarData();
}
@ -1396,23 +1418,19 @@ const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
bool DSAStackTy::hasExplicitDSA(
const ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred,
unsigned Level, bool NotLastprivate) const {
if (isStackEmpty())
if (getStackSize() <= Level)
return false;
D = getCanonicalDecl(D);
auto StartI = Stack.back().first.begin();
auto EndI = Stack.back().first.end();
if (std::distance(StartI, EndI) <= (int)Level)
return false;
std::advance(StartI, Level);
auto I = StartI->SharingMap.find(D);
if ((I != StartI->SharingMap.end()) &&
I->getSecond().RefExpr.getPointer() &&
CPred(I->getSecond().Attributes) &&
(!NotLastprivate || !I->getSecond().RefExpr.getInt()))
const SharingMapTy &StackElem = getStackElemAtLevel(Level);
auto I = StackElem.SharingMap.find(D);
if (I != StackElem.SharingMap.end() &&
I->getSecond().RefExpr.getPointer() &&
CPred(I->getSecond().Attributes) &&
(!NotLastprivate || !I->getSecond().RefExpr.getInt()))
return true;
// Check predetermined rules for the loop control variables.
auto LI = StartI->LCVMap.find(D);
if (LI != StartI->LCVMap.end())
auto LI = StackElem.LCVMap.find(D);
if (LI != StackElem.LCVMap.end())
return CPred(OMPC_private);
return false;
}
@ -1420,14 +1438,10 @@ bool DSAStackTy::hasExplicitDSA(
bool DSAStackTy::hasExplicitDirective(
const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
unsigned Level) const {
if (isStackEmpty())
if (getStackSize() <= Level)
return false;
auto StartI = Stack.back().first.begin();
auto EndI = Stack.back().first.end();
if (std::distance(StartI, EndI) <= (int)Level)
return false;
std::advance(StartI, Level);
return DPred(StartI->Directive);
const SharingMapTy &StackElem = getStackElemAtLevel(Level);
return DPred(StackElem.Directive);
}
bool DSAStackTy::hasDirective(
@ -1436,13 +1450,9 @@ bool DSAStackTy::hasDirective(
DPred,
bool FromParent) const {
// We look only in the enclosing region.
if (isStackEmpty())
return false;
auto StartI = std::next(Stack.back().first.rbegin());
auto EndI = Stack.back().first.rend();
if (FromParent && StartI != EndI)
StartI = std::next(StartI);
for (auto I = StartI, EE = EndI; I != EE; ++I) {
size_t Skip = FromParent ? 2 : 1;
for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
I != E; ++I) {
if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
return true;
}