diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 5251e85d56c8..63867fab5767 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -494,7 +494,8 @@ public: // - Define module variables and OpenMP/OpenACC declarative constructs so // they are available before lowering any function that may use them. bool hasMainProgram = false; - const Fortran::semantics::Symbol *globalOmpRequiresSymbol = nullptr; + llvm::SmallVector + globalOmpRequiresSymbols; createBuilderOutsideOfFuncOpAndDo([&]() { for (Fortran::lower::pft::Program::Units &u : pft.getUnits()) { Fortran::common::visit( @@ -503,8 +504,7 @@ public: if (f.isMainProgram()) hasMainProgram = true; declareFunction(f); - if (!globalOmpRequiresSymbol) - globalOmpRequiresSymbol = f.getScope().symbol(); + globalOmpRequiresSymbols.push_back(f.getScope().symbol()); }, [&](Fortran::lower::pft::ModuleLikeUnit &m) { lowerModuleDeclScope(m); @@ -512,12 +512,15 @@ public: m.containedUnitList) if (auto *f = std::get_if( - &unit)) + &unit)) { declareFunction(*f); + globalOmpRequiresSymbols.push_back( + f->getScope().symbol()); + } + globalOmpRequiresSymbols.push_back(m.getScope().symbol()); }, [&](Fortran::lower::pft::BlockDataUnit &b) { - if (!globalOmpRequiresSymbol) - globalOmpRequiresSymbol = b.symTab.symbol(); + globalOmpRequiresSymbols.push_back(b.symTab.symbol()); }, [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {}, [&](Fortran::lower::pft::OpenACCDirectiveUnit &d) {}, @@ -567,7 +570,7 @@ public: Fortran::common::LanguageFeature::Coarray)); }); - finalizeOpenMPLowering(globalOmpRequiresSymbol); + finalizeOpenMPLowering(globalOmpRequiresSymbols); } /// Declare a function. @@ -7201,7 +7204,8 @@ private: /// Performing OpenMP lowering actions that were deferred to the end of /// lowering. void finalizeOpenMPLowering( - const Fortran::semantics::Symbol *globalOmpRequiresSymbol) { + llvm::SmallVectorImpl + &globalOmpRequiresSymbol) { if (!ompDeferredDeclareTarget.empty()) { bool deferredDeviceFuncFound = Fortran::lower::markOpenMPDeferredDeclareTargetFunctions( @@ -7210,9 +7214,10 @@ private: } // Set the module attribute related to OpenMP requires directives - if (ompDeviceCodeFound) - Fortran::lower::genOpenMPRequires(getModuleOp().getOperation(), - globalOmpRequiresSymbol); + if (ompDeviceCodeFound) { + for (const Fortran::semantics::Symbol *sym : globalOmpRequiresSymbol) + Fortran::lower::genOpenMPRequires(getModuleOp().getOperation(), sym); + } } /// Record fir.dummy_scope operation for this function. diff --git a/flang/test/Lower/OpenMP/requires-usm.f90 b/flang/test/Lower/OpenMP/requires-usm.f90 new file mode 100644 index 000000000000..eb5b84cdba78 --- /dev/null +++ b/flang/test/Lower/OpenMP/requires-usm.f90 @@ -0,0 +1,56 @@ +! RUN: split-file %s %t + +! Verify that we pick up requires USM and apply it correctly when it is specified +! outside of the program. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp %t/requires-usm.f90 -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %t/requires-usm.f90 -o - | FileCheck %s +! RUN: bbc -fopenmp -emit-hlfir %t/requires-usm.f90 -o - | FileCheck %s +! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-hlfir %t/requires-usm.f90 -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp %t/requires-usm-subroutine-after.f90 -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %t/requires-usm-subroutine-after.f90 -o - | FileCheck %s +! RUN: bbc -fopenmp -emit-hlfir %t/requires-usm-subroutine-after.f90 -o - | FileCheck %s +! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-hlfir %t/requires-usm-subroutine-after.f90 -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp %t/requires-usm-program-after.f90 -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %t/requires-usm-program-after.f90 -o - | FileCheck %s +! RUN: bbc -fopenmp -emit-hlfir %t/requires-usm-program-after.f90 -o - | FileCheck %s +! RUN: bbc -fopenmp -fopenmp-is-target-device -emit-hlfir %t/requires-usm-program-after.f90 -o - | FileCheck %s + +! CHECK: module attributes { +! CHECK-SAME: omp.requires = #omp + +!--- requires-usm.f90 +module declare_mod + implicit none +!$omp requires unified_shared_memory + contains +end module + +program main + use declare_mod + implicit none +!$omp target +!$omp end target +end program + +!--- requires-usm-subroutine-after.f90 +program main + implicit none +end program main + +subroutine test + !$omp requires unified_shared_memory +!$omp target +!$omp end target +end subroutine + +!--- requires-usm-program-after.f90 +subroutine test +end subroutine + +program main + implicit none +!$omp requires unified_shared_memory +!$omp target +!$omp end target +end program main