From 5366bba3b492666fcc0445d58e5ab5b0a0206839 Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Fri, 23 May 2025 11:25:16 -0300 Subject: [PATCH 1/2] [flang][OpenMP] Explicitly set Shared DSA in symbols Before this change, OmpShared was not always set in shared symbols. Instead, absence of private flags was interpreted as shared DSA. The problem was that symbols with no flags, with only a host association, could also mean "has same DSA as in the enclosing context". Now shared symbols behave the same as private and can be treated the same way. Because of the host association symbols with no flags mentioned above, it was also incorrect to simply test the flags of a given symbol to find out if it was private or shared. The function GetSymbolDSA() was added to fix this. It would be better to avoid the need of these special symbols, but this would require changes to how symbols are collected in lowering. Besides that, some semantic checks need to know if a DSA clause was used or not. To avoid confusing implicit symbols with DSA clauses a new flag was added: OmpExplicit. It is now set for all symbols with explicitly determined data-sharing attributes. With the changes above, AddToContextObjectWithDSA() and the symbol to DSA map could probably be removed and the DSA could be obtained directly from the symbol, but this was not attempted. Some debug messages were also added, with the "omp" DEBUG_TYPE, to make it easier to debug the creation of implicit symbols and to visualize all associations of a given symbol. Fixes #130533 Fixes #140882 --- flang/include/flang/Semantics/openmp-dsa.h | 20 ++ flang/include/flang/Semantics/symbol.h | 5 +- flang/lib/Lower/Bridge.cpp | 4 +- flang/lib/Semantics/CMakeLists.txt | 1 + flang/lib/Semantics/openmp-dsa.cpp | 29 ++ flang/lib/Semantics/resolve-directives.cpp | 302 +++++++++++++----- flang/test/Semantics/OpenMP/common-block.f90 | 6 +- flang/test/Semantics/OpenMP/copyprivate03.f90 | 12 + .../test/Semantics/OpenMP/default-clause.f90 | 6 +- .../Semantics/OpenMP/do05-positivecase.f90 | 6 +- flang/test/Semantics/OpenMP/do20.f90 | 2 +- flang/test/Semantics/OpenMP/forall.f90 | 4 +- flang/test/Semantics/OpenMP/implicit-dsa.f90 | 35 +- flang/test/Semantics/OpenMP/reduction08.f90 | 20 +- flang/test/Semantics/OpenMP/reduction09.f90 | 14 +- flang/test/Semantics/OpenMP/reduction11.f90 | 2 +- flang/test/Semantics/OpenMP/scan2.f90 | 4 +- flang/test/Semantics/OpenMP/symbol01.f90 | 12 +- flang/test/Semantics/OpenMP/symbol02.f90 | 8 +- flang/test/Semantics/OpenMP/symbol03.f90 | 8 +- flang/test/Semantics/OpenMP/symbol04.f90 | 4 +- flang/test/Semantics/OpenMP/symbol05.f90 | 2 +- flang/test/Semantics/OpenMP/symbol06.f90 | 2 +- flang/test/Semantics/OpenMP/symbol07.f90 | 4 +- flang/test/Semantics/OpenMP/symbol08.f90 | 36 +-- flang/test/Semantics/OpenMP/symbol09.f90 | 4 +- 26 files changed, 381 insertions(+), 171 deletions(-) create mode 100644 flang/include/flang/Semantics/openmp-dsa.h create mode 100644 flang/lib/Semantics/openmp-dsa.cpp diff --git a/flang/include/flang/Semantics/openmp-dsa.h b/flang/include/flang/Semantics/openmp-dsa.h new file mode 100644 index 0000000000000..4b94a679f29ef --- /dev/null +++ b/flang/include/flang/Semantics/openmp-dsa.h @@ -0,0 +1,20 @@ +//===-- include/flang/Semantics/openmp-dsa.h --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_SEMANTICS_OPENMP_DSA_H_ +#define FORTRAN_SEMANTICS_OPENMP_DSA_H_ + +#include "flang/Semantics/symbol.h" + +namespace Fortran::semantics { + +Symbol::Flags GetSymbolDSA(const Symbol &symbol); + +} // namespace Fortran::semantics + +#endif // FORTRAN_SEMANTICS_OPENMP_DSA_H_ diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 9ebdd3a8081ed..cec212f0eae37 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -785,8 +785,9 @@ class Symbol { OmpAllocate, OmpDeclarativeAllocateDirective, OmpExecutableAllocateDirective, OmpDeclareSimd, OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock, - OmpIfSpecified, OmpNone, OmpPreDetermined, OmpImplicit, OmpDependObject, - OmpInclusiveScan, OmpExclusiveScan, OmpInScanReduction, OmpUniform); + OmpIfSpecified, OmpNone, OmpPreDetermined, OmpExplicit, OmpImplicit, + OmpDependObject, OmpInclusiveScan, OmpExclusiveScan, OmpInScanReduction, + OmpUniform); using Flags = common::EnumSet; const Scope &owner() const { return *owner_; } diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 4e6db3eaa990d..1970c2263f318 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -59,6 +59,7 @@ #include "flang/Optimizer/Transforms/Passes.h" #include "flang/Parser/parse-tree.h" #include "flang/Runtime/iostat-consts.h" +#include "flang/Semantics/openmp-dsa.h" #include "flang/Semantics/runtime-type-info.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/tools.h" @@ -1387,7 +1388,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (isUnordered || sym.has() || sym.has()) { if (!shallowLookupSymbol(sym) && - !sym.test(Fortran::semantics::Symbol::Flag::OmpShared)) { + !GetSymbolDSA(sym).test( + Fortran::semantics::Symbol::Flag::OmpShared)) { // Do concurrent loop variables are not mapped yet since they are local // to the Do concurrent scope (same for OpenMP loops). mlir::OpBuilder::InsertPoint insPt = builder->saveInsertionPoint(); diff --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt index bd8cc47365f06..18c89587843a9 100644 --- a/flang/lib/Semantics/CMakeLists.txt +++ b/flang/lib/Semantics/CMakeLists.txt @@ -32,6 +32,7 @@ add_flang_library(FortranSemantics dump-expr.cpp expression.cpp mod-file.cpp + openmp-dsa.cpp openmp-modifiers.cpp pointer-assignment.cpp program-tree.cpp diff --git a/flang/lib/Semantics/openmp-dsa.cpp b/flang/lib/Semantics/openmp-dsa.cpp new file mode 100644 index 0000000000000..48aa36febe5c5 --- /dev/null +++ b/flang/lib/Semantics/openmp-dsa.cpp @@ -0,0 +1,29 @@ +//===-- flang/lib/Semantics/openmp-dsa.cpp ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "flang/Semantics/openmp-dsa.h" + +namespace Fortran::semantics { + +Symbol::Flags GetSymbolDSA(const Symbol &symbol) { + Symbol::Flags dsaFlags{Symbol::Flag::OmpPrivate, + Symbol::Flag::OmpFirstPrivate, Symbol::Flag::OmpLastPrivate, + Symbol::Flag::OmpShared, Symbol::Flag::OmpLinear, + Symbol::Flag::OmpReduction}; + Symbol::Flags dsa{symbol.flags() & dsaFlags}; + if (dsa.any()) { + return dsa; + } + // If no DSA are set use those from the host associated symbol, if any. + if (const auto *details{symbol.detailsIf()}) { + return GetSymbolDSA(details->symbol()); + } + return {}; +} + +} // namespace Fortran::semantics diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 6884607edebb3..c62a2b9d1310f 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -19,9 +19,11 @@ #include "flang/Parser/parse-tree.h" #include "flang/Parser/tools.h" #include "flang/Semantics/expression.h" +#include "flang/Semantics/openmp-dsa.h" #include "flang/Semantics/openmp-modifiers.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/tools.h" +#include "llvm/Support/Debug.h" #include #include #include @@ -111,10 +113,9 @@ template class DirectiveAttributeVisitor { const parser::Name *GetLoopIndex(const parser::DoConstruct &); const parser::DoConstruct *GetDoConstructIf( const parser::ExecutionPartConstruct &); - Symbol *DeclareNewPrivateAccessEntity(const Symbol &, Symbol::Flag, Scope &); - Symbol *DeclarePrivateAccessEntity( - const parser::Name &, Symbol::Flag, Scope &); - Symbol *DeclarePrivateAccessEntity(Symbol &, Symbol::Flag, Scope &); + Symbol *DeclareNewAccessEntity(const Symbol &, Symbol::Flag, Scope &); + Symbol *DeclareAccessEntity(const parser::Name &, Symbol::Flag, Scope &); + Symbol *DeclareAccessEntity(Symbol &, Symbol::Flag, Scope &); Symbol *DeclareOrMarkOtherAccessEntity(const parser::Name &, Symbol::Flag); UnorderedSymbolSet dataSharingAttributeObjects_; // on one directive @@ -754,11 +755,11 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { Symbol::Flags ompFlagsRequireNewSymbol{Symbol::Flag::OmpPrivate, Symbol::Flag::OmpLinear, Symbol::Flag::OmpFirstPrivate, - Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpReduction, - Symbol::Flag::OmpCriticalLock, Symbol::Flag::OmpCopyIn, - Symbol::Flag::OmpUseDevicePtr, Symbol::Flag::OmpUseDeviceAddr, - Symbol::Flag::OmpIsDevicePtr, Symbol::Flag::OmpHasDeviceAddr, - Symbol::Flag::OmpUniform}; + Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpShared, + Symbol::Flag::OmpReduction, Symbol::Flag::OmpCriticalLock, + Symbol::Flag::OmpCopyIn, Symbol::Flag::OmpUseDevicePtr, + Symbol::Flag::OmpUseDeviceAddr, Symbol::Flag::OmpIsDevicePtr, + Symbol::Flag::OmpHasDeviceAddr, Symbol::Flag::OmpUniform}; Symbol::Flags ompFlagsRequireMark{Symbol::Flag::OmpThreadprivate, Symbol::Flag::OmpDeclareTarget, Symbol::Flag::OmpExclusiveScan, @@ -835,8 +836,24 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { void IssueNonConformanceWarning( llvm::omp::Directive D, parser::CharBlock source); - void CreateImplicitSymbols( - const Symbol *symbol, std::optional setFlag = std::nullopt); + void CreateImplicitSymbols(const Symbol *symbol); + + void AddToContextObjectWithExplicitDSA(Symbol &symbol, Symbol::Flag flag) { + AddToContextObjectWithDSA(symbol, flag); + if (dataSharingAttributeFlags.test(flag)) { + symbol.set(Symbol::Flag::OmpExplicit); + } + } + + // Clear any previous data-sharing attribute flags and set the new ones. + // Needed when setting PreDetermined DSAs, that take precedence over + // Implicit ones. + void SetSymbolDSA(Symbol &symbol, Symbol::Flags flags) { + symbol.flags() &= ~(dataSharingAttributeFlags | + Symbol::Flags{Symbol::Flag::OmpExplicit, Symbol::Flag::OmpImplicit, + Symbol::Flag::OmpPreDetermined}); + symbol.flags() |= flags; + } }; template @@ -873,7 +890,7 @@ const parser::DoConstruct *DirectiveAttributeVisitor::GetDoConstructIf( } template -Symbol *DirectiveAttributeVisitor::DeclareNewPrivateAccessEntity( +Symbol *DirectiveAttributeVisitor::DeclareNewAccessEntity( const Symbol &object, Symbol::Flag flag, Scope &scope) { assert(object.owner() != currScope()); auto &symbol{MakeAssocSymbol(object.name(), object, scope)}; @@ -886,20 +903,20 @@ Symbol *DirectiveAttributeVisitor::DeclareNewPrivateAccessEntity( } template -Symbol *DirectiveAttributeVisitor::DeclarePrivateAccessEntity( +Symbol *DirectiveAttributeVisitor::DeclareAccessEntity( const parser::Name &name, Symbol::Flag flag, Scope &scope) { if (!name.symbol) { return nullptr; // not resolved by Name Resolution step, do nothing } - name.symbol = DeclarePrivateAccessEntity(*name.symbol, flag, scope); + name.symbol = DeclareAccessEntity(*name.symbol, flag, scope); return name.symbol; } template -Symbol *DirectiveAttributeVisitor::DeclarePrivateAccessEntity( +Symbol *DirectiveAttributeVisitor::DeclareAccessEntity( Symbol &object, Symbol::Flag flag, Scope &scope) { if (object.owner() != currScope()) { - return DeclareNewPrivateAccessEntity(object, flag, scope); + return DeclareNewAccessEntity(object, flag, scope); } else { object.set(flag); return &object; @@ -1606,6 +1623,20 @@ void AccAttributeVisitor::CheckMultipleAppearances( } } +#ifndef NDEBUG + +#define DEBUG_TYPE "omp" + +static llvm::raw_ostream &operator<<( + llvm::raw_ostream &os, const Symbol::Flags &flags); + +namespace dbg { +static void DumpAssocSymbols(llvm::raw_ostream &os, const Symbol &sym); +static std::string ScopeSourcePos(const Fortran::semantics::Scope &scope); +} // namespace dbg + +#endif + bool OmpAttributeVisitor::Pre(const parser::OpenMPBlockConstruct &x) { const auto &beginBlockDir{std::get(x.t)}; const auto &beginDir{std::get(beginBlockDir.t)}; @@ -1798,12 +1829,12 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct( } } } - // If this symbol is already Private or Firstprivate in the enclosing - // OpenMP parallel or task then there is nothing to do here. + // If this symbol already has an explicit data-sharing attribute in the + // enclosing OpenMP parallel or task then there is nothing to do here. if (auto *symbol{targetIt->scope.FindSymbol(iv.source)}) { if (symbol->owner() == targetIt->scope) { - if (symbol->test(Symbol::Flag::OmpPrivate) || - symbol->test(Symbol::Flag::OmpFirstPrivate)) { + if (symbol->test(Symbol::Flag::OmpExplicit) && + (symbol->flags() & dataSharingAttributeFlags).any()) { return; } } @@ -1812,7 +1843,8 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct( // parallel or task if (auto *symbol{ResolveOmp(iv, Symbol::Flag::OmpPrivate, targetIt->scope)}) { targetIt++; - symbol->set(Symbol::Flag::OmpPreDetermined); + SetSymbolDSA( + *symbol, {Symbol::Flag::OmpPreDetermined, Symbol::Flag::OmpPrivate}); iv.symbol = symbol; // adjust the symbol within region for (auto it{dirContext_.rbegin()}; it != targetIt; ++it) { AddToContextObjectWithDSA(*symbol, Symbol::Flag::OmpPrivate, *it); @@ -1924,7 +1956,7 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( const parser::Name *iv{GetLoopIndex(*loop)}; if (iv) { if (auto *symbol{ResolveOmp(*iv, ivDSA, currScope())}) { - symbol->set(Symbol::Flag::OmpPreDetermined); + SetSymbolDSA(*symbol, {Symbol::Flag::OmpPreDetermined, ivDSA}); iv->symbol = symbol; // adjust the symbol within region AddToContextObjectWithDSA(*symbol, ivDSA); } @@ -2184,42 +2216,48 @@ static bool IsPrivatizable(const Symbol *sym) { misc->kind() != MiscDetails::Kind::ConstructName)); } -void OmpAttributeVisitor::CreateImplicitSymbols( - const Symbol *symbol, std::optional setFlag) { +void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) { if (!IsPrivatizable(symbol)) { return; } + LLVM_DEBUG(llvm::dbgs() << "CreateImplicitSymbols: " << *symbol << '\n'); + // Implicitly determined DSAs // OMP 5.2 5.1.1 - Variables Referenced in a Construct Symbol *lastDeclSymbol = nullptr; - std::optional prevDSA; + Symbol::Flags prevDSA; for (int dirDepth{0}; dirDepth < (int)dirContext_.size(); ++dirDepth) { DirContext &dirContext = dirContext_[dirDepth]; - std::optional dsa; + Symbol::Flags dsa; - for (auto symMap : dirContext.objectWithDSA) { - // if the `symbol` already has a data-sharing attribute - if (symMap.first->name() == symbol->name()) { - dsa = symMap.second; - break; + Scope &scope{context_.FindScope(dirContext.directiveSource)}; + auto it{scope.find(symbol->name())}; + if (it != scope.end()) { + // There is already a symbol in the current scope, use its DSA. + dsa = GetSymbolDSA(*it->second); + } else { + for (auto symMap : dirContext.objectWithDSA) { + if (symMap.first->name() == symbol->name()) { + // `symbol` already has a data-sharing attribute in the current + // context, use it. + dsa.set(symMap.second); + break; + } } } // When handling each implicit rule for a given symbol, one of the - // following 3 actions may be taken: - // 1. Declare a new private symbol. - // 2. Create a new association symbol with no flags, that will represent - // a shared symbol in the current scope. Note that symbols without - // any private flags are considered as shared. - // 3. Use the last declared private symbol, by inserting a new symbol - // in the scope being processed, associated with it. - // If no private symbol was declared previously, then no association - // is needed and the symbol from the enclosing scope will be - // inherited by the current one. + // following actions may be taken: + // 1. Declare a new private or shared symbol. + // 2. Use the last declared symbol, by inserting a new symbol in the + // scope being processed, associated with it. + // If no symbol was declared previously, then no association is needed + // and the symbol from the enclosing scope will be inherited by the + // current one. // // Because of how symbols are collected in lowering, not inserting a new - // symbol in the last case could lead to the conclusion that a symbol + // symbol in the second case could lead to the conclusion that a symbol // from an enclosing construct was declared in the current construct, // which would result in wrong privatization code being generated. // Consider the following example: @@ -2237,46 +2275,71 @@ void OmpAttributeVisitor::CreateImplicitSymbols( // it would have the private flag set. // This would make x appear to be defined in p2, causing it to be // privatized in p2 and its privatization in p1 to be skipped. - auto makePrivateSymbol = [&](Symbol::Flag flag) { + auto makeSymbol = [&](Symbol::Flags flags) { const Symbol *hostSymbol = lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate(); - lastDeclSymbol = DeclareNewPrivateAccessEntity( + assert(flags.LeastElement()); + Symbol::Flag flag = *flags.LeastElement(); + lastDeclSymbol = DeclareNewAccessEntity( *hostSymbol, flag, context_.FindScope(dirContext.directiveSource)); - if (setFlag) { - lastDeclSymbol->set(*setFlag); - } + lastDeclSymbol->flags() |= flags; return lastDeclSymbol; }; - auto makeSharedSymbol = [&](std::optional flag = {}) { - const Symbol *hostSymbol = - lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate(); - Symbol &assocSymbol = MakeAssocSymbol(symbol->name(), *hostSymbol, - context_.FindScope(dirContext.directiveSource)); - if (flag) { - assocSymbol.set(*flag); - } - }; auto useLastDeclSymbol = [&]() { if (lastDeclSymbol) { - makeSharedSymbol(); + const Symbol *hostSymbol = + lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate(); + MakeAssocSymbol(symbol->name(), *hostSymbol, + context_.FindScope(dirContext.directiveSource)); } }; +#ifndef NDEBUG + auto printImplicitRule = [&](const char *id) { + LLVM_DEBUG(llvm::dbgs() << "\t" << id << ": dsa: " << dsa << '\n'); + LLVM_DEBUG( + llvm::dbgs() << "\t\tScope: " << dbg::ScopeSourcePos(scope) << '\n'); + }; +#define PRINT_IMPLICIT_RULE(id) printImplicitRule(id) +#else +#define PRINT_IMPLICIT_RULE(id) +#endif + bool taskGenDir = llvm::omp::taskGeneratingSet.test(dirContext.directive); bool targetDir = llvm::omp::allTargetSet.test(dirContext.directive); bool parallelDir = llvm::omp::allParallelSet.test(dirContext.directive); bool teamsDir = llvm::omp::allTeamsSet.test(dirContext.directive); - if (dsa.has_value()) { - if (dsa.value() == Symbol::Flag::OmpShared && - (parallelDir || taskGenDir || teamsDir)) { - makeSharedSymbol(Symbol::Flag::OmpShared); + if (dsa.any()) { + if (parallelDir || taskGenDir || teamsDir) { + Symbol *prevDeclSymbol{lastDeclSymbol}; + // NOTE As `dsa` will match that of the symbol in the current scope + // (if any), we won't override the DSA of any existing symbol. + if ((dsa & dataSharingAttributeFlags).any()) { + makeSymbol(dsa); + } + // Fix host association of explicit symbols, as they can be created + // before implicit ones in enclosing scope. + if (prevDeclSymbol && prevDeclSymbol != lastDeclSymbol && + lastDeclSymbol->test(Symbol::Flag::OmpExplicit)) { + const auto *hostAssoc{lastDeclSymbol->detailsIf()}; + if (hostAssoc && hostAssoc->symbol() != *prevDeclSymbol) { + lastDeclSymbol->set_details(HostAssocDetails{*prevDeclSymbol}); + } + } } - // Private symbols will have been declared already. prevDSA = dsa; + PRINT_IMPLICIT_RULE("0) already has DSA"); continue; } + // NOTE Because of how lowering uses OmpImplicit flag, we can only set it + // for symbols with private DSA. + // Also, as the default clause is handled separately in lowering, + // don't mark its symbols with OmpImplicit either. + // Ideally, lowering should be changed and all implicit symbols + // should be marked with OmpImplicit. + if (dirContext.defaultDSA == Symbol::Flag::OmpPrivate || dirContext.defaultDSA == Symbol::Flag::OmpFirstPrivate || dirContext.defaultDSA == Symbol::Flag::OmpShared) { @@ -2285,33 +2348,34 @@ void OmpAttributeVisitor::CreateImplicitSymbols( if (!parallelDir && !taskGenDir && !teamsDir) { return; } - if (dirContext.defaultDSA != Symbol::Flag::OmpShared) { - makePrivateSymbol(dirContext.defaultDSA); - } else { - makeSharedSymbol(); - } - dsa = dirContext.defaultDSA; + dsa = {dirContext.defaultDSA}; + makeSymbol(dsa); + PRINT_IMPLICIT_RULE("1) default"); } else if (parallelDir) { // 2) parallel -> shared - makeSharedSymbol(); - dsa = Symbol::Flag::OmpShared; + dsa = {Symbol::Flag::OmpShared}; + makeSymbol(dsa); + PRINT_IMPLICIT_RULE("2) parallel"); } else if (!taskGenDir && !targetDir) { // 3) enclosing context - useLastDeclSymbol(); dsa = prevDSA; + useLastDeclSymbol(); + PRINT_IMPLICIT_RULE("3) enclosing context"); } else if (targetDir) { // TODO 4) not mapped target variable -> firstprivate dsa = prevDSA; } else if (taskGenDir) { // TODO 5) dummy arg in orphaned taskgen construct -> firstprivate - if (prevDSA == Symbol::Flag::OmpShared) { + if (prevDSA.test(Symbol::Flag::OmpShared)) { // 6) shared in enclosing context -> shared - makeSharedSymbol(); - dsa = Symbol::Flag::OmpShared; + dsa = {Symbol::Flag::OmpShared}; + makeSymbol(dsa); + PRINT_IMPLICIT_RULE("6) taskgen: shared"); } else { // 7) firstprivate - dsa = Symbol::Flag::OmpFirstPrivate; - makePrivateSymbol(*dsa)->set(Symbol::Flag::OmpImplicit); + dsa = {Symbol::Flag::OmpFirstPrivate}; + makeSymbol(dsa)->set(Symbol::Flag::OmpImplicit); + PRINT_IMPLICIT_RULE("7) taskgen: firstprivate"); } } prevDSA = dsa; @@ -2377,7 +2441,7 @@ void OmpAttributeVisitor::ResolveOmpName( if (ResolveName(&name)) { if (auto *resolvedSymbol{ResolveOmp(name, ompFlag, currScope())}) { if (dataSharingAttributeFlags.test(ompFlag)) { - AddToContextObjectWithDSA(*resolvedSymbol, ompFlag); + AddToContextObjectWithExplicitDSA(*resolvedSymbol, ompFlag); } } } else if (ompFlag == Symbol::Flag::OmpCriticalLock) { @@ -2490,7 +2554,7 @@ void OmpAttributeVisitor::ResolveOmpObject( if (dataCopyingAttributeFlags.test(ompFlag)) { CheckDataCopyingClause(*name, *symbol, ompFlag); } else { - AddToContextObjectWithDSA(*symbol, ompFlag); + AddToContextObjectWithExplicitDSA(*symbol, ompFlag); if (dataSharingAttributeFlags.test(ompFlag)) { CheckMultipleAppearances(*name, *symbol, ompFlag); } @@ -2594,8 +2658,14 @@ void OmpAttributeVisitor::ResolveOmpObject( GetContext().directive))) { for (Symbol::Flag ompFlag1 : dataMappingAttributeFlags) { for (Symbol::Flag ompFlag2 : dataSharingAttributeFlags) { - checkExclusivelists( - hostAssocSym, ompFlag1, symbol, ompFlag2); + if ((hostAssocSym->test(ompFlag2) && + hostAssocSym->test( + Symbol::Flag::OmpExplicit)) || + (symbol->test(ompFlag2) && + symbol->test(Symbol::Flag::OmpExplicit))) { + checkExclusivelists( + hostAssocSym, ompFlag1, symbol, ompFlag2); + } } } } @@ -2630,7 +2700,7 @@ void OmpAttributeVisitor::ResolveOmpObject( if (dataCopyingAttributeFlags.test(ompFlag)) { CheckDataCopyingClause(name, *resolvedObject, ompFlag); } else { - AddToContextObjectWithDSA(*resolvedObject, ompFlag); + AddToContextObjectWithExplicitDSA(*resolvedObject, ompFlag); } details.replace_object(*resolvedObject, index); } @@ -2649,7 +2719,7 @@ void OmpAttributeVisitor::ResolveOmpObject( Symbol *OmpAttributeVisitor::ResolveOmp( const parser::Name &name, Symbol::Flag ompFlag, Scope &scope) { if (ompFlagsRequireNewSymbol.test(ompFlag)) { - return DeclarePrivateAccessEntity(name, ompFlag, scope); + return DeclareAccessEntity(name, ompFlag, scope); } else { return DeclareOrMarkOtherAccessEntity(name, ompFlag); } @@ -2658,7 +2728,7 @@ Symbol *OmpAttributeVisitor::ResolveOmp( Symbol *OmpAttributeVisitor::ResolveOmp( Symbol &symbol, Symbol::Flag ompFlag, Scope &scope) { if (ompFlagsRequireNewSymbol.test(ompFlag)) { - return DeclarePrivateAccessEntity(symbol, ompFlag, scope); + return DeclareAccessEntity(symbol, ompFlag, scope); } else { return DeclareOrMarkOtherAccessEntity(symbol, ompFlag); } @@ -2837,10 +2907,16 @@ static bool IsSymbolThreadprivate(const Symbol &symbol) { } static bool IsSymbolPrivate(const Symbol &symbol) { - if (symbol.test(Symbol::Flag::OmpPrivate) || - symbol.test(Symbol::Flag::OmpFirstPrivate)) { + LLVM_DEBUG(llvm::dbgs() << "IsSymbolPrivate(" << symbol.name() << "):\n"); + LLVM_DEBUG(dbg::DumpAssocSymbols(llvm::dbgs(), symbol)); + + if (Symbol::Flags dsa{GetSymbolDSA(symbol)}; dsa.any()) { + if (dsa.test(Symbol::Flag::OmpShared)) { + return false; + } return true; } + // A symbol that has not gone through constructs that may privatize the // original symbol may be predetermined as private. // (OMP 5.2 5.1.1 - Variables Referenced in a Construct) @@ -3086,4 +3162,60 @@ void OmpAttributeVisitor::IssueNonConformanceWarning( context_.Warn(common::UsageWarning::OpenMPUsage, source, "%s"_warn_en_US, warnStrOS.str()); } + +#ifndef NDEBUG + +static llvm::raw_ostream &operator<<( + llvm::raw_ostream &os, const Symbol::Flags &flags) { + flags.Dump(os, Symbol::EnumToString); + return os; +} + +namespace dbg { + +static llvm::raw_ostream &operator<<( + llvm::raw_ostream &os, std::optional srcPos) { + if (srcPos) { + os << *srcPos.value().path << ":" << srcPos.value().line << ": "; + } + return os; +} + +static std::optional GetSourcePosition( + const Fortran::semantics::Scope &scope, + const Fortran::parser::CharBlock &src) { + parser::AllCookedSources &allCookedSources{ + scope.context().allCookedSources()}; + if (std::optional prange{ + allCookedSources.GetProvenanceRange(src)}) { + return allCookedSources.allSources().GetSourcePosition(prange->start()); + } + return std::nullopt; +} + +// Returns a string containing the source location of `scope` followed by +// its first source line. +static std::string ScopeSourcePos(const Fortran::semantics::Scope &scope) { + const parser::CharBlock &sourceRange{scope.sourceRange()}; + std::string src{sourceRange.ToString()}; + size_t nl{src.find('\n')}; + std::string str; + llvm::raw_string_ostream ss{str}; + + ss << GetSourcePosition(scope, sourceRange) << src.substr(0, nl); + return str; +} + +static void DumpAssocSymbols(llvm::raw_ostream &os, const Symbol &sym) { + os << '\t' << sym << '\n'; + os << "\t\tOwner: " << ScopeSourcePos(sym.owner()) << '\n'; + if (const auto *details{sym.detailsIf()}) { + DumpAssocSymbols(os, details->symbol()); + } +} + +} // namespace dbg + +#endif + } // namespace Fortran::semantics diff --git a/flang/test/Semantics/OpenMP/common-block.f90 b/flang/test/Semantics/OpenMP/common-block.f90 index e1ddd120da857..93f29b12eacae 100644 --- a/flang/test/Semantics/OpenMP/common-block.f90 +++ b/flang/test/Semantics/OpenMP/common-block.f90 @@ -10,9 +10,9 @@ program main common /blk/ a, b, c !$omp parallel private(/blk/) !CHECK: OtherConstruct scope: size=0 alignment=1 - !CHECK: a (OmpPrivate): HostAssoc - !CHECK: b (OmpPrivate): HostAssoc - !CHECK: c (OmpPrivate): HostAssoc + !CHECK: a (OmpPrivate, OmpExplicit): HostAssoc + !CHECK: b (OmpPrivate, OmpExplicit): HostAssoc + !CHECK: c (OmpPrivate, OmpExplicit): HostAssoc call sub(a, b, c) !$omp end parallel end program diff --git a/flang/test/Semantics/OpenMP/copyprivate03.f90 b/flang/test/Semantics/OpenMP/copyprivate03.f90 index 9d39fdb6b13c8..fae190645b5e7 100644 --- a/flang/test/Semantics/OpenMP/copyprivate03.f90 +++ b/flang/test/Semantics/OpenMP/copyprivate03.f90 @@ -6,6 +6,8 @@ program omp_copyprivate integer :: a(10), b(10) + real, dimension(:), allocatable :: c + real, dimension(:), pointer :: d integer, save :: k !$omp threadprivate(k) @@ -43,4 +45,14 @@ program omp_copyprivate print *, a, b + !$omp task + !$omp parallel private(c, d) + allocate(c(5)) + allocate(d(10)) + !$omp single + c = 22 + d = 33 + !$omp end single copyprivate(c, d) + !$omp end parallel + !$omp end task end program omp_copyprivate diff --git a/flang/test/Semantics/OpenMP/default-clause.f90 b/flang/test/Semantics/OpenMP/default-clause.f90 index 9cde77be2babe..d4c38ea56de53 100644 --- a/flang/test/Semantics/OpenMP/default-clause.f90 +++ b/flang/test/Semantics/OpenMP/default-clause.f90 @@ -15,8 +15,8 @@ program sample !CHECK: OtherConstruct scope: size=0 alignment=1 !CHECK: a (OmpPrivate): HostAssoc !CHECK: k (OmpPrivate): HostAssoc - !CHECK: x (OmpFirstPrivate): HostAssoc - !CHECK: y (OmpPrivate): HostAssoc + !CHECK: x (OmpFirstPrivate, OmpExplicit): HostAssoc + !CHECK: y (OmpPrivate, OmpExplicit): HostAssoc !CHECK: z (OmpPrivate): HostAssoc !$omp parallel default(private) !CHECK: OtherConstruct scope: size=0 alignment=1 @@ -34,7 +34,7 @@ program sample !$omp parallel default(firstprivate) shared(y) private(w) !CHECK: OtherConstruct scope: size=0 alignment=1 !CHECK: k (OmpFirstPrivate): HostAssoc - !CHECK: w (OmpPrivate): HostAssoc + !CHECK: w (OmpPrivate, OmpExplicit): HostAssoc !CHECK: z (OmpFirstPrivate): HostAssoc y = 30 w = 40 diff --git a/flang/test/Semantics/OpenMP/do05-positivecase.f90 b/flang/test/Semantics/OpenMP/do05-positivecase.f90 index 5e1b1b86f72f6..8481cb2fc2ca0 100644 --- a/flang/test/Semantics/OpenMP/do05-positivecase.f90 +++ b/flang/test/Semantics/OpenMP/do05-positivecase.f90 @@ -20,12 +20,12 @@ program omp_do !$omp parallel default(shared) !$omp do !DEF: /omp_do/OtherConstruct2/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) - !DEF: /omp_do/OtherConstruct2/n HostAssoc INTEGER(4) + !DEF: /omp_do/OtherConstruct2/OtherConstruct1/n HostAssoc INTEGER(4) do i=1,n !$omp parallel !$omp single !DEF: /work EXTERNAL (Subroutine) ProcEntity - !DEF: /omp_do/OtherConstruct2/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4) + !DEF: /omp_do/OtherConstruct2/OtherConstruct1/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4) call work(i, 1) !$omp end single !$omp end parallel @@ -34,7 +34,7 @@ program omp_do !$omp end parallel !$omp parallel private(i) - !DEF: /omp_do/OtherConstruct3/i (OmpPrivate) HostAssoc INTEGER(4) + !DEF: /omp_do/OtherConstruct3/i (OmpPrivate, OmpExplicit) HostAssoc INTEGER(4) do i=1,10 !$omp single print *, "hello" diff --git a/flang/test/Semantics/OpenMP/do20.f90 b/flang/test/Semantics/OpenMP/do20.f90 index 040a82079590f..ee305ad1a34cf 100644 --- a/flang/test/Semantics/OpenMP/do20.f90 +++ b/flang/test/Semantics/OpenMP/do20.f90 @@ -10,7 +10,7 @@ subroutine shared_iv !$omp parallel shared(i) !$omp single - !DEF: /shared_iv/OtherConstruct1/i (OmpShared) HostAssoc INTEGER(4) + !DEF: /shared_iv/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4) do i = 0, 1 end do !$omp end single diff --git a/flang/test/Semantics/OpenMP/forall.f90 b/flang/test/Semantics/OpenMP/forall.f90 index 58492664a4e85..b862b4b27641b 100644 --- a/flang/test/Semantics/OpenMP/forall.f90 +++ b/flang/test/Semantics/OpenMP/forall.f90 @@ -18,8 +18,8 @@ !$omp parallel !DEF: /MainProgram1/OtherConstruct1/Forall1/i (Implicit) ObjectEntity INTEGER(4) - !DEF: /MainProgram1/OtherConstruct1/a HostAssoc INTEGER(4) - !DEF: /MainProgram1/OtherConstruct1/b HostAssoc INTEGER(4) + !DEF: /MainProgram1/OtherConstruct1/a (OmpShared) HostAssoc INTEGER(4) + !DEF: /MainProgram1/OtherConstruct1/b (OmpShared) HostAssoc INTEGER(4) forall(i = 1:5) a(i) = b(i) * 2 !$omp end parallel diff --git a/flang/test/Semantics/OpenMP/implicit-dsa.f90 b/flang/test/Semantics/OpenMP/implicit-dsa.f90 index a7ed834b0f1c6..7e38435274b7b 100644 --- a/flang/test/Semantics/OpenMP/implicit-dsa.f90 +++ b/flang/test/Semantics/OpenMP/implicit-dsa.f90 @@ -14,15 +14,15 @@ subroutine implicit_dsa_test1 !$omp task private(y) shared(z) !DEF: /implicit_dsa_test1/OtherConstruct1/x (OmpFirstPrivate, OmpImplicit) HostAssoc INTEGER(4) - !DEF: /implicit_dsa_test1/OtherConstruct1/y (OmpPrivate) HostAssoc INTEGER(4) - !DEF: /implicit_dsa_test1/OtherConstruct1/z (OmpShared) HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test1/OtherConstruct1/y (OmpPrivate, OmpExplicit) HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test1/OtherConstruct1/z (OmpShared, OmpExplicit) HostAssoc INTEGER(4) x = y + z !$omp end task !$omp task default(shared) - !DEF: /implicit_dsa_test1/OtherConstruct2/x HostAssoc INTEGER(4) - !DEF: /implicit_dsa_test1/OtherConstruct2/y HostAssoc INTEGER(4) - !DEF: /implicit_dsa_test1/OtherConstruct2/z HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test1/OtherConstruct2/x (OmpShared) HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test1/OtherConstruct2/y (OmpShared) HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test1/OtherConstruct2/z (OmpShared) HostAssoc INTEGER(4) x = y + z !$omp end task @@ -61,16 +61,16 @@ subroutine implicit_dsa_test3 !$omp parallel !$omp task - !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct1/x HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct1/x (OmpShared) HostAssoc INTEGER(4) x = 1 - !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct1/y HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct1/y (OmpShared) HostAssoc INTEGER(4) y = 1 !$omp end task !$omp task firstprivate(x) - !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct2/x (OmpFirstPrivate) HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct2/x (OmpFirstPrivate, OmpExplicit) HostAssoc INTEGER(4) x = 1 - !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct2/z HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test3/OtherConstruct1/OtherConstruct2/z (OmpShared) HostAssoc INTEGER(4) z = 1 !$omp end task !$omp end parallel @@ -110,7 +110,7 @@ subroutine implicit_dsa_test5 !$omp parallel default(private) !$omp task !$omp parallel - !DEF: /implicit_dsa_test5/OtherConstruct1/OtherConstruct1/OtherConstruct1/x HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test5/OtherConstruct1/OtherConstruct1/OtherConstruct1/x (OmpShared) HostAssoc INTEGER(4) x = 1 !$omp end parallel !$omp end task @@ -133,7 +133,7 @@ subroutine implicit_dsa_test6 !$omp end parallel !$omp parallel default(firstprivate) shared(y) - !DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/y (OmpShared) HostAssoc INTEGER(4) + !DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/y (OmpShared, OmpExplicit) HostAssoc INTEGER(4) !DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/x (OmpFirstPrivate) HostAssocINTEGER(4) !DEF: /implicit_dsa_test6/OtherConstruct1/OtherConstruct2/z (OmpFirstPrivate) HostAssocINTEGER(4) y = x + z @@ -156,3 +156,16 @@ subroutine implicit_dsa_test7 !$omp end taskgroup !$omp end task end subroutine + +! Predetermined loop iteration variable. +!DEF: /implicit_dsa_test8 (Subroutine) Subprogram +subroutine implicit_dsa_test8 + !DEF: /implicit_dsa_test8/i ObjectEntity INTEGER(4) + integer i + + !$omp task + !DEF: /implicit_dsa_test8/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i = 1, 10 + end do + !$omp end task +end subroutine diff --git a/flang/test/Semantics/OpenMP/reduction08.f90 b/flang/test/Semantics/OpenMP/reduction08.f90 index 9442fbd4d5978..01a06eb7d7414 100644 --- a/flang/test/Semantics/OpenMP/reduction08.f90 +++ b/flang/test/Semantics/OpenMP/reduction08.f90 @@ -13,9 +13,9 @@ program omp_reduction !$omp parallel do reduction(max:k) !DEF: /omp_reduction/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct1/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) !DEF: /omp_reduction/max ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct1/m HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct1/m (OmpShared) HostAssoc INTEGER(4) k = max(k, m) end do !$omp end parallel do @@ -23,9 +23,9 @@ program omp_reduction !$omp parallel do reduction(min:k) !DEF: /omp_reduction/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct2/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct2/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) !DEF: /omp_reduction/min ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct2/m HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct2/m (OmpShared) HostAssoc INTEGER(4) k = min(k, m) end do !$omp end parallel do @@ -33,9 +33,9 @@ program omp_reduction !$omp parallel do reduction(iand:k) !DEF: /omp_reduction/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct3/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct3/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) !DEF: /omp_reduction/iand ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct3/m HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct3/m (OmpShared) HostAssoc INTEGER(4) k = iand(k, m) end do !$omp end parallel do @@ -43,9 +43,9 @@ program omp_reduction !$omp parallel do reduction(ior:k) !DEF: /omp_reduction/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct4/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct4/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) !DEF: /omp_reduction/ior ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct4/m HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct4/m (OmpShared) HostAssoc INTEGER(4) k = ior(k, m) end do !$omp end parallel do @@ -53,9 +53,9 @@ program omp_reduction !$omp parallel do reduction(ieor:k) !DEF: /omp_reduction/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct5/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct5/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) !DEF: /omp_reduction/ieor ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /omp_reduction/OtherConstruct5/m HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct5/m (OmpShared) HostAssoc INTEGER(4) k = ieor(k,m) end do !$omp end parallel do diff --git a/flang/test/Semantics/OpenMP/reduction09.f90 b/flang/test/Semantics/OpenMP/reduction09.f90 index 1af2fc4fd9691..d6c71c30d2834 100644 --- a/flang/test/Semantics/OpenMP/reduction09.f90 +++ b/flang/test/Semantics/OpenMP/reduction09.f90 @@ -16,7 +16,7 @@ program omp_reduction !$omp do reduction(+:k) !DEF: /omp_reduction/OtherConstruct1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct1/OtherConstruct1/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct1/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) k = k+1 end do !$omp end do @@ -26,7 +26,7 @@ program omp_reduction !$omp parallel do reduction(+:a(10)) !DEF: /omp_reduction/OtherConstruct2/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct2/k HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct2/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do @@ -35,7 +35,7 @@ program omp_reduction !$omp parallel do reduction(+:a(1:10:1)) !DEF: /omp_reduction/OtherConstruct3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct3/k HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct3/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do @@ -43,7 +43,7 @@ program omp_reduction !$omp parallel do reduction(+:b(1:10:1,1:5,2)) !DEF: /omp_reduction/OtherConstruct4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct4/k HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct4/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do @@ -51,7 +51,7 @@ program omp_reduction !$omp parallel do reduction(+:b(1:10:1,1:5,2:5:1)) !DEF: /omp_reduction/OtherConstruct5/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct5/k HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct5/k (OmpShared) HostAssoc INTEGER(4) k = k+1 end do !$omp end parallel do @@ -60,7 +60,7 @@ program omp_reduction !$omp do reduction(+:k) reduction(+:j) !DEF: /omp_reduction/OtherConstruct6/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct6/OtherConstruct1/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct6/OtherConstruct1/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) k = k+1 end do !$omp end do @@ -69,7 +69,7 @@ program omp_reduction !$omp do reduction(+:k) reduction(*:j) reduction(+:l) !DEF: /omp_reduction/OtherConstruct7/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /omp_reduction/OtherConstruct7/k (OmpReduction) HostAssoc INTEGER(4) + !DEF: /omp_reduction/OtherConstruct7/k (OmpReduction, OmpExplicit) HostAssoc INTEGER(4) k = k+1 end do !$omp end do diff --git a/flang/test/Semantics/OpenMP/reduction11.f90 b/flang/test/Semantics/OpenMP/reduction11.f90 index 3893fe70b407f..b2ad0f6a6ee11 100644 --- a/flang/test/Semantics/OpenMP/reduction11.f90 +++ b/flang/test/Semantics/OpenMP/reduction11.f90 @@ -12,7 +12,7 @@ program omp_reduction ! CHECK: OtherConstruct scope ! CHECK: i (OmpPrivate, OmpPreDetermined): HostAssoc - ! CHECK: k (OmpReduction): HostAssoc + ! CHECK: k (OmpReduction, OmpExplicit): HostAssoc ! CHECK: max, INTRINSIC: ProcEntity !$omp parallel do reduction(max:k) do i=1,10 diff --git a/flang/test/Semantics/OpenMP/scan2.f90 b/flang/test/Semantics/OpenMP/scan2.f90 index 5232e63aa6b4f..ffe84910f88a2 100644 --- a/flang/test/Semantics/OpenMP/scan2.f90 +++ b/flang/test/Semantics/OpenMP/scan2.f90 @@ -12,13 +12,13 @@ program omp_reduction ! CHECK: OtherConstruct scope ! CHECK: i (OmpPrivate, OmpPreDetermined): HostAssoc - ! CHECK: k (OmpReduction, OmpInclusiveScan, OmpInScanReduction): HostAssoc + ! CHECK: k (OmpReduction, OmpExplicit, OmpInclusiveScan, OmpInScanReduction): HostAssoc !$omp parallel do reduction(inscan, +:k) do i=1,10 !$omp scan inclusive(k) end do !$omp end parallel do - ! CHECK: m (OmpReduction, OmpExclusiveScan, OmpInScanReduction): HostAssoc + ! CHECK: m (OmpReduction, OmpExplicit, OmpExclusiveScan, OmpInScanReduction): HostAssoc !$omp parallel do reduction(inscan, +:m) do i=1,10 !$omp scan exclusive(m) diff --git a/flang/test/Semantics/OpenMP/symbol01.f90 b/flang/test/Semantics/OpenMP/symbol01.f90 index a40a8563fde1f..595b6b89c84fd 100644 --- a/flang/test/Semantics/OpenMP/symbol01.f90 +++ b/flang/test/Semantics/OpenMP/symbol01.f90 @@ -47,22 +47,22 @@ program mm !$omp parallel do private(a,t,/c/) shared(c) !DEF: /mm/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /mm/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4) - !DEF: /mm/OtherConstruct1/b HostAssoc INTEGER(4) + !DEF: /mm/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) + !DEF: /mm/OtherConstruct1/b (OmpShared) HostAssoc INTEGER(4) !REF: /mm/OtherConstruct1/i a = a+b(i) - !DEF: /mm/OtherConstruct1/t (OmpPrivate) HostAssoc TYPE(myty) + !DEF: /mm/OtherConstruct1/t (OmpPrivate, OmpExplicit) HostAssoc TYPE(myty) !REF: /md/myty/a !REF: /mm/OtherConstruct1/i t%a = i - !DEF: /mm/OtherConstruct1/y (OmpPrivate) HostAssoc REAL(4) + !DEF: /mm/OtherConstruct1/y (OmpPrivate, OmpExplicit) HostAssoc REAL(4) y = 0. - !DEF: /mm/OtherConstruct1/x (OmpPrivate) HostAssoc REAL(4) + !DEF: /mm/OtherConstruct1/x (OmpPrivate, OmpExplicit) HostAssoc REAL(4) !REF: /mm/OtherConstruct1/a !REF: /mm/OtherConstruct1/i !REF: /mm/OtherConstruct1/y x = a+i+y - !DEF: /mm/OtherConstruct1/c (OmpShared) HostAssoc REAL(4) + !DEF: /mm/OtherConstruct1/c (OmpShared, OmpExplicit) HostAssoc REAL(4) c = 3.0 end do end program diff --git a/flang/test/Semantics/OpenMP/symbol02.f90 b/flang/test/Semantics/OpenMP/symbol02.f90 index 31d9cb2e46ba8..9007da042845a 100644 --- a/flang/test/Semantics/OpenMP/symbol02.f90 +++ b/flang/test/Semantics/OpenMP/symbol02.f90 @@ -11,13 +11,13 @@ !DEF: /MainProgram1/c (Implicit) ObjectEntity REAL(4) c = 0 !$omp parallel private(a,b) shared(c,d) - !DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) a = 3. - !DEF: /MainProgram1/OtherConstruct1/b (OmpPrivate) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/b (OmpPrivate, OmpExplicit) HostAssoc REAL(4) b = 4 - !DEF: /MainProgram1/OtherConstruct1/c (OmpShared) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/c (OmpShared, OmpExplicit) HostAssoc REAL(4) c = 5 - !DEF: /MainProgram1/OtherConstruct1/d (OmpShared) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/d (OmpShared, OmpExplicit) HostAssoc REAL(4) d = 6 !$omp end parallel !DEF: /MainProgram1/a (Implicit) ObjectEntity REAL(4) diff --git a/flang/test/Semantics/OpenMP/symbol03.f90 b/flang/test/Semantics/OpenMP/symbol03.f90 index 08defb40e56a7..d67c1fdf333c4 100644 --- a/flang/test/Semantics/OpenMP/symbol03.f90 +++ b/flang/test/Semantics/OpenMP/symbol03.f90 @@ -7,14 +7,14 @@ !DEF: /MainProgram1/b (Implicit) ObjectEntity REAL(4) b = 2 !$omp parallel private(a) shared(b) - !DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) a = 3. - !DEF: /MainProgram1/OtherConstruct1/b (OmpShared) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/b (OmpShared, OmpExplicit) HostAssoc REAL(4) b = 4 !$omp parallel private(b) shared(a) - !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/a (OmpShared) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/a (OmpShared, OmpExplicit) HostAssoc REAL(4) a = 5. - !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/b (OmpPrivate) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/b (OmpPrivate, OmpExplicit) HostAssoc REAL(4) b = 6 !$omp end parallel !$omp end parallel diff --git a/flang/test/Semantics/OpenMP/symbol04.f90 b/flang/test/Semantics/OpenMP/symbol04.f90 index 808d1e0dd09be..834b166266376 100644 --- a/flang/test/Semantics/OpenMP/symbol04.f90 +++ b/flang/test/Semantics/OpenMP/symbol04.f90 @@ -9,12 +9,12 @@ !REF: /MainProgram1/a a = 3.14 !$omp parallel private(a) - !DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(8) + !DEF: /MainProgram1/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(8) a = 2. !$omp do private(a) !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(8) + !DEF: /MainProgram1/OtherConstruct1/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(8) a = 1. end do !$omp end parallel diff --git a/flang/test/Semantics/OpenMP/symbol05.f90 b/flang/test/Semantics/OpenMP/symbol05.f90 index 1ad0c10a40135..fe01f15d20aa3 100644 --- a/flang/test/Semantics/OpenMP/symbol05.f90 +++ b/flang/test/Semantics/OpenMP/symbol05.f90 @@ -15,7 +15,7 @@ subroutine foo !DEF: /mm/foo/a ObjectEntity INTEGER(4) integer :: a = 3 !$omp parallel - !DEF: /mm/foo/OtherConstruct1/a HostAssoc INTEGER(4) + !DEF: /mm/foo/OtherConstruct1/a (OmpShared) HostAssoc INTEGER(4) a = 1 !DEF: /mm/i PUBLIC (Implicit, OmpThreadprivate) ObjectEntity INTEGER(4) !REF: /mm/foo/OtherConstruct1/a diff --git a/flang/test/Semantics/OpenMP/symbol06.f90 b/flang/test/Semantics/OpenMP/symbol06.f90 index 906264eb12642..daf3874b79af6 100644 --- a/flang/test/Semantics/OpenMP/symbol06.f90 +++ b/flang/test/Semantics/OpenMP/symbol06.f90 @@ -10,7 +10,7 @@ !$omp parallel do firstprivate(a) lastprivate(a) !DEF: /MainProgram1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,10 - !DEF: /MainProgram1/OtherConstruct1/a (OmpFirstPrivate, OmpLastPrivate) HostAssoc REAL(4) + !DEF: /MainProgram1/OtherConstruct1/a (OmpFirstPrivate, OmpLastPrivate, OmpExplicit) HostAssoc REAL(4) a = 2. end do end program diff --git a/flang/test/Semantics/OpenMP/symbol07.f90 b/flang/test/Semantics/OpenMP/symbol07.f90 index a375942ebb1d9..86b7305411347 100644 --- a/flang/test/Semantics/OpenMP/symbol07.f90 +++ b/flang/test/Semantics/OpenMP/symbol07.f90 @@ -21,9 +21,9 @@ subroutine function_call_in_region !DEF: /function_call_in_region/b ObjectEntity REAL(4) real :: b = 5. !$omp parallel default(none) private(a) shared(b) - !DEF: /function_call_in_region/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4) + !DEF: /function_call_in_region/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) !REF: /function_call_in_region/foo - !DEF: /function_call_in_region/OtherConstruct1/b (OmpShared) HostAssoc REAL(4) + !DEF: /function_call_in_region/OtherConstruct1/b (OmpShared, OmpExplicit) HostAssoc REAL(4) a = foo(b) !$omp end parallel !REF: /function_call_in_region/a diff --git a/flang/test/Semantics/OpenMP/symbol08.f90 b/flang/test/Semantics/OpenMP/symbol08.f90 index 80ae1c6d2242b..545bccc86b068 100644 --- a/flang/test/Semantics/OpenMP/symbol08.f90 +++ b/flang/test/Semantics/OpenMP/symbol08.f90 @@ -28,19 +28,19 @@ subroutine test_do !DEF: /test_do/k ObjectEntity INTEGER(4) integer i, j, k !$omp parallel - !DEF: /test_do/OtherConstruct1/i HostAssoc INTEGER(4) + !DEF: /test_do/OtherConstruct1/i (OmpShared) HostAssoc INTEGER(4) i = 99 !$omp do collapse(2) !DEF: /test_do/OtherConstruct1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,5 !DEF: /test_do/OtherConstruct1/OtherConstruct1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do j=6,10 - !DEF: /test_do/OtherConstruct1/a HostAssoc REAL(4) + !DEF: /test_do/OtherConstruct1/OtherConstruct1/a HostAssoc REAL(4) a(1,1,1) = 0. !DEF: /test_do/OtherConstruct1/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do k=11,15 - !REF: /test_do/OtherConstruct1/a - !REF: /test_do/OtherConstruct1/k + !REF: /test_do/OtherConstruct1/OtherConstruct1/a + !DEF: /test_do/OtherConstruct1/OtherConstruct1/k HostAssoc INTEGER(4) !REF: /test_do/OtherConstruct1/OtherConstruct1/j !REF: /test_do/OtherConstruct1/OtherConstruct1/i a(k,j,i) = 1. @@ -65,9 +65,9 @@ subroutine test_pardo do i=1,5 !DEF: /test_pardo/OtherConstruct1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do j=6,10 - !DEF: /test_pardo/OtherConstruct1/a HostAssoc REAL(4) + !DEF: /test_pardo/OtherConstruct1/a (OmpShared) HostAssoc REAL(4) a(1,1,1) = 0. - !DEF: /test_pardo/OtherConstruct1/k (OmpPrivate) HostAssoc INTEGER(4) + !DEF: /test_pardo/OtherConstruct1/k (OmpPrivate, OmpExplicit) HostAssoc INTEGER(4) do k=11,15 !REF: /test_pardo/OtherConstruct1/a !REF: /test_pardo/OtherConstruct1/k @@ -91,7 +91,7 @@ subroutine test_taskloop !$omp taskloop private(j) !DEF: /test_taskloop/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do i=1,5 - !DEF: /test_taskloop/OtherConstruct1/j (OmpPrivate) HostAssoc INTEGER(4) + !DEF: /test_taskloop/OtherConstruct1/j (OmpPrivate, OmpExplicit) HostAssoc INTEGER(4) !REF: /test_taskloop/OtherConstruct1/i do j=1,i !DEF: /test_taskloop/OtherConstruct1/a (OmpFirstPrivate, OmpImplicit) HostAssoc REAL(4) @@ -139,15 +139,15 @@ subroutine dotprod (b, c, n, block_size, num_teams, block_threads) do i0=1,n,block_size !$omp parallel do reduction(+: sum) !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) - !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/i0 HostAssoc INTEGER(4) + !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/i0 (OmpShared) HostAssoc INTEGER(4) !DEF: /dotprod/min ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity - !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/block_size HostAssoc INTEGER(4) - !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/n HostAssoc INTEGER(4) + !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/block_size (OmpShared) HostAssoc INTEGER(4) + !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/n (OmpShared) HostAssoc INTEGER(4) do i=i0,min(i0+block_size, n) - !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/sum (OmpReduction) HostAssoc REAL(4) - !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/b HostAssoc REAL(4) + !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/sum (OmpReduction, OmpExplicit) HostAssoc REAL(4) + !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/b (OmpShared) HostAssoc REAL(4) !REF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/i - !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/c HostAssoc REAL(4) + !DEF: /dotprod/OtherConstruct1/OtherConstruct1/OtherConstruct1/OtherConstruct1/c (OmpShared) HostAssoc REAL(4) sum = sum+b(i)*c(i) end do end do @@ -175,7 +175,7 @@ subroutine test_simd do j=6,10 !DEF: /test_simd/OtherConstruct1/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do k=11,15 - !DEF: /test_simd/OtherConstruct1/a HostAssoc REAL(4) + !DEF: /test_simd/OtherConstruct1/a (OmpShared) HostAssoc REAL(4) !REF: /test_simd/OtherConstruct1/k !REF: /test_simd/OtherConstruct1/j !REF: /test_simd/OtherConstruct1/i @@ -202,7 +202,7 @@ subroutine test_simd_multi do j=6,10 !DEF: /test_simd_multi/OtherConstruct1/k (OmpLastPrivate, OmpPreDetermined) HostAssoc INTEGER(4) do k=11,15 - !DEF: /test_simd_multi/OtherConstruct1/a HostAssoc REAL(4) + !DEF: /test_simd_multi/OtherConstruct1/a (OmpShared) HostAssoc REAL(4) !REF: /test_simd_multi/OtherConstruct1/k !REF: /test_simd_multi/OtherConstruct1/j !REF: /test_simd_multi/OtherConstruct1/i @@ -224,11 +224,11 @@ subroutine test_seq_loop !REF: /test_seq_loop/j j = -1 !$omp parallel - !DEF: /test_seq_loop/OtherConstruct1/i HostAssoc INTEGER(4) - !DEF: /test_seq_loop/OtherConstruct1/j HostAssoc INTEGER(4) + !DEF: /test_seq_loop/OtherConstruct1/i (OmpShared) HostAssoc INTEGER(4) + !DEF: /test_seq_loop/OtherConstruct1/j (OmpShared) HostAssoc INTEGER(4) print *, i, j !$omp parallel - !DEF: /test_seq_loop/OtherConstruct1/OtherConstruct1/i HostAssoc INTEGER(4) + !DEF: /test_seq_loop/OtherConstruct1/OtherConstruct1/i (OmpShared) HostAssoc INTEGER(4) !DEF: /test_seq_loop/OtherConstruct1/OtherConstruct1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) print *, i, j !$omp do diff --git a/flang/test/Semantics/OpenMP/symbol09.f90 b/flang/test/Semantics/OpenMP/symbol09.f90 index a375942ebb1d9..86b7305411347 100644 --- a/flang/test/Semantics/OpenMP/symbol09.f90 +++ b/flang/test/Semantics/OpenMP/symbol09.f90 @@ -21,9 +21,9 @@ subroutine function_call_in_region !DEF: /function_call_in_region/b ObjectEntity REAL(4) real :: b = 5. !$omp parallel default(none) private(a) shared(b) - !DEF: /function_call_in_region/OtherConstruct1/a (OmpPrivate) HostAssoc REAL(4) + !DEF: /function_call_in_region/OtherConstruct1/a (OmpPrivate, OmpExplicit) HostAssoc REAL(4) !REF: /function_call_in_region/foo - !DEF: /function_call_in_region/OtherConstruct1/b (OmpShared) HostAssoc REAL(4) + !DEF: /function_call_in_region/OtherConstruct1/b (OmpShared, OmpExplicit) HostAssoc REAL(4) a = foo(b) !$omp end parallel !REF: /function_call_in_region/a From cf64aac606702563d289039e73102e85aed0dbab Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Fri, 30 May 2025 15:33:44 -0300 Subject: [PATCH 2/2] Add a comment explaining a new test --- flang/test/Semantics/OpenMP/copyprivate03.f90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flang/test/Semantics/OpenMP/copyprivate03.f90 b/flang/test/Semantics/OpenMP/copyprivate03.f90 index fae190645b5e7..249b27e4b2b86 100644 --- a/flang/test/Semantics/OpenMP/copyprivate03.f90 +++ b/flang/test/Semantics/OpenMP/copyprivate03.f90 @@ -52,6 +52,8 @@ program omp_copyprivate !$omp single c = 22 d = 33 + !Check that 'c' and 'd' inherit PRIVATE DSA from the enclosing PARALLEL + !and no error occurs. !$omp end single copyprivate(c, d) !$omp end parallel !$omp end task