26
26
#include " flang/Optimizer/HLFIR/HLFIROps.h"
27
27
#include " flang/Semantics/attr.h"
28
28
#include " flang/Semantics/tools.h"
29
+ #include " llvm/ADT/Sequence.h"
30
+ #include " llvm/ADT/SmallSet.h"
29
31
30
32
namespace Fortran {
31
33
namespace lower {
@@ -49,7 +51,7 @@ DataSharingProcessor::DataSharingProcessor(
49
51
firOpBuilder (converter.getFirOpBuilder()), clauses(clauses), eval(eval),
50
52
shouldCollectPreDeterminedSymbols(shouldCollectPreDeterminedSymbols),
51
53
useDelayedPrivatization(useDelayedPrivatization), symTable(symTable),
52
- visitor() {
54
+ visitor(semaCtx ) {
53
55
eval.visit ([&](const auto &functionParserNode) {
54
56
parser::Walk (functionParserNode, visitor);
55
57
});
@@ -424,24 +426,55 @@ getSource(const semantics::SemanticsContext &semaCtx,
424
426
return source;
425
427
}
426
428
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
+
427
458
bool 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));
437
469
}
438
470
439
471
bool DataSharingProcessor::isOpenMPPrivatizingEvaluation (
440
472
const pft::Evaluation &eval) const {
441
- return eval.visit ([](auto &&s) {
473
+ unsigned version = semaCtx.langOptions ().OpenMPVersion ;
474
+ return eval.visit ([=](auto &&s) {
442
475
using BareS = llvm::remove_cvref_t <decltype (s)>;
443
476
if constexpr (std::is_same_v<BareS, parser::OpenMPConstruct>) {
444
- return isOpenMPPrivatizingConstruct (s);
477
+ return isOpenMPPrivatizingConstruct (s, version );
445
478
} else {
446
479
return false ;
447
480
}
0 commit comments