2626#include " flang/Optimizer/HLFIR/HLFIROps.h"
2727#include " flang/Semantics/attr.h"
2828#include " flang/Semantics/tools.h"
29+ #include " llvm/ADT/Sequence.h"
30+ #include " llvm/ADT/SmallSet.h"
2931
3032namespace Fortran {
3133namespace lower {
@@ -49,7 +51,7 @@ DataSharingProcessor::DataSharingProcessor(
4951 firOpBuilder (converter.getFirOpBuilder()), clauses(clauses), eval(eval),
5052 shouldCollectPreDeterminedSymbols(shouldCollectPreDeterminedSymbols),
5153 useDelayedPrivatization(useDelayedPrivatization), symTable(symTable),
52- visitor() {
54+ visitor(semaCtx ) {
5355 eval.visit ([&](const auto &functionParserNode) {
5456 parser::Walk (functionParserNode, visitor);
5557 });
@@ -424,24 +426,55 @@ getSource(const semantics::SemanticsContext &semaCtx,
424426 return source;
425427}
426428
429+ static void collectPrivatizingConstructs (
430+ llvm::SmallSet<llvm::omp::Directive, 16 > &constructs, unsigned version) {
431+ using Clause = llvm::omp::Clause;
432+ using Directive = llvm::omp::Directive;
433+
434+ static const Clause privatizingClauses[] = {
435+ Clause::OMPC_private,
436+ Clause::OMPC_lastprivate,
437+ Clause::OMPC_firstprivate,
438+ Clause::OMPC_in_reduction,
439+ Clause::OMPC_reduction,
440+ Clause::OMPC_linear,
441+ // TODO: Clause::OMPC_induction,
442+ Clause::OMPC_task_reduction,
443+ Clause::OMPC_detach,
444+ Clause::OMPC_use_device_ptr,
445+ Clause::OMPC_is_device_ptr,
446+ };
447+
448+ for (auto dir : llvm::enum_seq_inclusive<Directive>(Directive::First_,
449+ Directive::Last_)) {
450+ bool allowsPrivatizing = llvm::any_of (privatizingClauses, [&](Clause cls) {
451+ return llvm::omp::isAllowedClauseForDirective (dir, cls, version);
452+ });
453+ if (allowsPrivatizing)
454+ constructs.insert (dir);
455+ }
456+ }
457+
427458bool DataSharingProcessor::isOpenMPPrivatizingConstruct (
428- const parser::OpenMPConstruct &omp) {
429- return common::visit (
430- [](auto &&s) {
431- using BareS = llvm::remove_cvref_t <decltype (s)>;
432- return std::is_same_v<BareS, parser::OpenMPBlockConstruct> ||
433- std::is_same_v<BareS, parser::OpenMPLoopConstruct> ||
434- std::is_same_v<BareS, parser::OpenMPSectionsConstruct>;
435- },
436- omp.u );
459+ const parser::OpenMPConstruct &omp, unsigned version) {
460+ static llvm::SmallSet<llvm::omp::Directive, 16 > privatizing;
461+ [[maybe_unused]] static bool init =
462+ (collectPrivatizingConstructs (privatizing, version), true );
463+
464+ // As of OpenMP 6.0, privatizing constructs (with the test being if they
465+ // allow a privatizing clause) are: dispatch, distribute, do, for, loop,
466+ // parallel, scope, sections, simd, single, target, target_data, task,
467+ // taskgroup, taskloop, and teams.
468+ return llvm::is_contained (privatizing, extractOmpDirective (omp));
437469}
438470
439471bool DataSharingProcessor::isOpenMPPrivatizingEvaluation (
440472 const pft::Evaluation &eval) const {
441- return eval.visit ([](auto &&s) {
473+ unsigned version = semaCtx.langOptions ().OpenMPVersion ;
474+ return eval.visit ([=](auto &&s) {
442475 using BareS = llvm::remove_cvref_t <decltype (s)>;
443476 if constexpr (std::is_same_v<BareS, parser::OpenMPConstruct>) {
444- return isOpenMPPrivatizingConstruct (s);
477+ return isOpenMPPrivatizingConstruct (s, version );
445478 } else {
446479 return false ;
447480 }
0 commit comments