llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-flang-openmp @llvm/pr-subscribers-flang-semantics Author: None (llvmbot) <details> <summary>Changes</summary> Backport 7ccdc06780b05bd8f31c20a9734fca2fbf275d7f Requested by: @<!-- -->kparzysz --- Full diff: https://github.com/llvm/llvm-project/pull/180203.diff 2 Files Affected: - (modified) flang/lib/Semantics/resolve-directives.cpp (+49-24) - (added) flang/test/Semantics/OpenMP/local-variables.f90 (+95) ``````````diff diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 6467abf872c16..9f2512713015c 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -388,6 +388,29 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> { explicit OmpAttributeVisitor(SemanticsContext &context) : DirectiveAttributeVisitor(context) {} + static bool HasStaticStorageDuration(const Symbol &symbol) { + auto &ultSym = symbol.GetUltimate(); + // Module-scope variable + return ultSym.owner().kind() == Scope::Kind::Module || + // Data statement variable + ultSym.flags().test(Symbol::Flag::InDataStmt) || + // Save attribute variable + ultSym.attrs().test(Attr::SAVE) || + // Referenced in a common block + ultSym.flags().test(Symbol::Flag::InCommonBlock); + } + + // Recognize symbols that are not created as a part of the OpenMP data- + // sharing processing, and that are declared inside of the construct. + // These symbols are predetermined private, but they shouldn't be marked + // in any special way, because there is nothing to be done for them. + // They are not symbols for which private copies need to be created, + // they are already themselves private. + static bool IsLocalInsideScope(const Symbol &symbol, const Scope &scope) { + return symbol.owner() != scope && scope.Contains(symbol.owner()) && + !HasStaticStorageDuration(symbol); + } + template <typename A> void Walk(const A &x) { parser::Walk(x, *this); } template <typename A> bool Pre(const A &) { return true; } template <typename A> void Post(const A &) {} @@ -2076,6 +2099,9 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct( break; } } + if (IsLocalInsideScope(*iv.symbol, targetIt->scope)) { + return; + } // If this symbol already has a data-sharing attribute then there is nothing // to do here. if (const Symbol * symbol{iv.symbol}) { @@ -2400,14 +2426,14 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel( } } // go through all the nested do-loops and resolve index variables - const parser::Name *iv{GetLoopIndex(*loop)}; - if (iv) { - if (auto *symbol{ResolveOmp(*iv, ivDSA, currScope())}) { - SetSymbolDSA(*symbol, {Symbol::Flag::OmpPreDetermined, ivDSA}); - iv->symbol = symbol; // adjust the symbol within region - AddToContextObjectWithDSA(*symbol, ivDSA); + if (const parser::Name *iv{GetLoopIndex(*loop)}) { + if (!iv->symbol || !IsLocalInsideScope(*iv->symbol, currScope())) { + if (auto *symbol{ResolveOmp(*iv, ivDSA, currScope())}) { + SetSymbolDSA(*symbol, {Symbol::Flag::OmpPreDetermined, ivDSA}); + iv->symbol = symbol; // adjust the symbol within region + AddToContextObjectWithDSA(*symbol, ivDSA); + } } - const auto &block{std::get<parser::Block>(loop->t)}; const auto it{block.begin()}; loop = it != block.end() ? GetDoConstructIf(*it) : nullptr; @@ -2651,20 +2677,6 @@ static bool IsPrivatizable(const Symbol *sym) { misc->kind() != MiscDetails::Kind::ConstructName)); } -static bool IsSymbolStaticStorageDuration(const Symbol &symbol) { - LLVM_DEBUG(llvm::dbgs() << "IsSymbolStaticStorageDuration(" << symbol.name() - << "):\n"); - auto ultSym = symbol.GetUltimate(); - // Module-scope variable - return (ultSym.owner().kind() == Scope::Kind::Module) || - // Data statement variable - (ultSym.flags().test(Symbol::Flag::InDataStmt)) || - // Save attribute variable - (ultSym.attrs().test(Attr::SAVE)) || - // Referenced in a common block - (ultSym.flags().test(Symbol::Flag::InCommonBlock)); -} - static bool IsTargetCaptureImplicitlyFirstprivatizeable(const Symbol &symbol, const Symbol::Flags &dsa, const Symbol::Flags &dataSharingAttributeFlags, const Symbol::Flags &dataMappingAttributeFlags, @@ -2823,7 +2835,9 @@ void OmpAttributeVisitor::CreateImplicitSymbols(const Symbol *symbol) { bool targetDir = llvm::omp::allTargetSet.test(dirContext.directive); bool parallelDir = llvm::omp::topParallelSet.test(dirContext.directive); bool teamsDir = llvm::omp::allTeamsSet.test(dirContext.directive); - bool isStaticStorageDuration = IsSymbolStaticStorageDuration(*symbol); + bool isStaticStorageDuration = HasStaticStorageDuration(*symbol); + LLVM_DEBUG(llvm::dbgs() + << "HasStaticStorageDuration(" << symbol->name() << "):\n"); if (dsa.any()) { if (parallelDir || taskGenDir || teamsDir) { @@ -2977,7 +2991,8 @@ void OmpAttributeVisitor::Post(const parser::Name &name) { auto *symbol{name.symbol}; if (symbol && WithinConstruct()) { - if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol)) { + if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol) && + !IsLocalInsideScope(*symbol, currScope())) { // TODO: create a separate function to go through the rules for // predetermined, explicitly determined, and implicitly // determined data-sharing attributes (2.15.1.1). @@ -3046,7 +3061,17 @@ void OmpAttributeVisitor::Post(const parser::Name &name) { return; } - CreateImplicitSymbols(symbol); + // We should only create any additional symbols, if the one mentioned + // in the source code was declared outside of the construct. This was + // always the case before Fortran 2008. F2008 introduced the BLOCK + // construct, and allowed local variable declarations. + // In OpenMP local (non-static) variables are always private in a given + // construct, if they are declared inside the construct. In those cases + // we don't need to do anything here (i.e. no flags are needed or + // anything else). + if (!IsLocalInsideScope(*symbol, currScope())) { + CreateImplicitSymbols(symbol); + } } // within OpenMP construct } diff --git a/flang/test/Semantics/OpenMP/local-variables.f90 b/flang/test/Semantics/OpenMP/local-variables.f90 new file mode 100644 index 0000000000000..8e7a220319605 --- /dev/null +++ b/flang/test/Semantics/OpenMP/local-variables.f90 @@ -0,0 +1,95 @@ +!RUN: %flang_fc1 -fdebug-unparse-with-symbols -fopenmp %s | FileCheck %s + +!Make sure that the local `bbb`s are their own entities. + +!CHECK-LABEL: !DEF: /f00 (Subroutine) Subprogram +!CHECK-NEXT: subroutine f00 +!CHECK-NEXT: !DEF: /f00/i ObjectEntity INTEGER(4) +!CHECK-NEXT: integer i +!CHECK-NEXT: !$omp parallel +!CHECK-NEXT: block +!CHECK-NEXT: block +!CHECK-NEXT: !DEF: /f00/OtherConstruct1/BlockConstruct1/BlockConstruct1/bbb ObjectEntity INTEGER(4) +!CHECK-NEXT: integer bbb +!CHECK-NEXT: !REF: /f00/OtherConstruct1/BlockConstruct1/BlockConstruct1/bbb +!CHECK-NEXT: bbb = 1 +!CHECK-NEXT: end block +!CHECK-NEXT: block +!CHECK-NEXT: !DEF: /f00/OtherConstruct1/BlockConstruct1/BlockConstruct2/bbb ObjectEntity INTEGER(4) +!CHECK-NEXT: integer bbb +!CHECK-NEXT: !REF: /f00/OtherConstruct1/BlockConstruct1/BlockConstruct2/bbb +!CHECK-NEXT: bbb = 2 +!CHECK-NEXT: end block +!CHECK-NEXT: end block +!CHECK-NEXT: !$omp end parallel +!CHECK-NEXT: end subroutine + +subroutine f00() + integer :: i + !$omp parallel + block + block + integer :: bbb + bbb = 1 + end block + block + integer :: bbb + bbb = 2 + end block + end block + !$omp end parallel +end subroutine + + +!CHECK-LABEL: !DEF: /f01 (Subroutine) Subprogram +!CHECK-NEXT: subroutine f01 +!CHECK-NEXT: !DEF: /f01/i ObjectEntity INTEGER(4) +!CHECK-NEXT: integer i +!CHECK-NEXT: !DEF: /f01/bbb ObjectEntity INTEGER(4) +!CHECK-NEXT: integer bbb +!CHECK-NEXT: !REF: /f01/bbb +!CHECK-NEXT: bbb = 0 +!CHECK-NEXT: !$omp parallel +!CHECK-NEXT: block +!CHECK-NEXT: !DEF: /f01/OtherConstruct1/bbb (OmpShared) HostAssoc INTEGER(4) +!CHECK-NEXT: bbb = 1234 +!CHECK-NEXT: block +!CHECK-NEXT: !DEF: /f01/OtherConstruct1/BlockConstruct1/BlockConstruct1/bbb ObjectEntity INTEGER(4) +!CHECK-NEXT: integer bbb +!CHECK-NEXT: !REF: /f01/OtherConstruct1/BlockConstruct1/BlockConstruct1/bbb +!CHECK-NEXT: bbb = 1 +!CHECK-NEXT: end block +!CHECK-NEXT: block +!CHECK-NEXT: !DEF: /f01/OtherConstruct1/BlockConstruct1/BlockConstruct2/bbb ObjectEntity INTEGER(4) +!CHECK-NEXT: integer bbb +!CHECK-NEXT: !REF: /f01/OtherConstruct1/BlockConstruct1/BlockConstruct2/bbb +!CHECK-NEXT: bbb = 2 +!CHECK-NEXT: end block +!CHECK-NEXT: end block +!CHECK-NEXT: !$omp end parallel +!CHECK-NEXT: !REF: /f01/bbb +!CHECK-NEXT: print *, bbb +!CHECK-NEXT: end subroutine + +subroutine f01() + integer :: i + integer :: bbb + + bbb = 0 + + !$omp parallel + block + bbb = 1234 + block + integer :: bbb + bbb = 1 + end block + block + integer :: bbb + bbb = 2 + end block + end block + !$omp end parallel + + print *, bbb +end subroutine `````````` </details> https://github.com/llvm/llvm-project/pull/180203 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
