Skip to content

Commit e295b0c

Browse files
authored
[flang][OpenMP] Fix detecting nested OpenMP constructs (#143383)
Recognize privatizing OpenMP constructs, and only exclude symbols from non-privatizing ones.
1 parent cde1035 commit e295b0c

File tree

4 files changed

+70
-16
lines changed

4 files changed

+70
-16
lines changed

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -388,19 +388,43 @@ getSource(const semantics::SemanticsContext &semaCtx,
388388
return source;
389389
}
390390

391+
bool DataSharingProcessor::isOpenMPPrivatizingConstruct(
392+
const parser::OpenMPConstruct &omp) {
393+
return common::visit(
394+
[](auto &&s) {
395+
using BareS = llvm::remove_cvref_t<decltype(s)>;
396+
return std::is_same_v<BareS, parser::OpenMPBlockConstruct> ||
397+
std::is_same_v<BareS, parser::OpenMPLoopConstruct> ||
398+
std::is_same_v<BareS, parser::OpenMPSectionsConstruct>;
399+
},
400+
omp.u);
401+
}
402+
403+
bool DataSharingProcessor::isOpenMPPrivatizingEvaluation(
404+
const pft::Evaluation &eval) const {
405+
return eval.visit([](auto &&s) {
406+
using BareS = llvm::remove_cvref_t<decltype(s)>;
407+
if constexpr (std::is_same_v<BareS, parser::OpenMPConstruct>) {
408+
return isOpenMPPrivatizingConstruct(s);
409+
} else {
410+
return false;
411+
}
412+
});
413+
}
414+
391415
void DataSharingProcessor::collectSymbolsInNestedRegions(
392416
lower::pft::Evaluation &eval, semantics::Symbol::Flag flag,
393417
llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions) {
394-
for (lower::pft::Evaluation &nestedEval : eval.getNestedEvaluations()) {
395-
if (nestedEval.hasNestedEvaluations()) {
396-
if (nestedEval.isConstruct())
397-
// Recursively look for OpenMP constructs within `nestedEval`'s region
398-
collectSymbolsInNestedRegions(nestedEval, flag, symbolsInNestedRegions);
399-
else {
400-
converter.collectSymbolSet(nestedEval, symbolsInNestedRegions, flag,
401-
/*collectSymbols=*/true,
402-
/*collectHostAssociatedSymbols=*/false);
403-
}
418+
if (!eval.hasNestedEvaluations())
419+
return;
420+
for (pft::Evaluation &nestedEval : eval.getNestedEvaluations()) {
421+
if (isOpenMPPrivatizingEvaluation(nestedEval)) {
422+
converter.collectSymbolSet(nestedEval, symbolsInNestedRegions, flag,
423+
/*collectSymbols=*/true,
424+
/*collectHostAssociatedSymbols=*/false);
425+
} else {
426+
// Recursively look for OpenMP constructs within `nestedEval`'s region
427+
collectSymbolsInNestedRegions(nestedEval, flag, symbolsInNestedRegions);
404428
}
405429
}
406430
}

flang/lib/Lower/OpenMP/DataSharingProcessor.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,22 @@ class DataSharingProcessor {
4545

4646
bool Pre(const parser::OpenMPConstruct &omp) {
4747
// Skip constructs that may not have privatizations.
48-
if (!std::holds_alternative<parser::OpenMPCriticalConstruct>(omp.u))
49-
currentConstruct = &omp;
48+
if (isOpenMPPrivatizingConstruct(omp))
49+
constructs.push_back(&omp);
5050
return true;
5151
}
5252

5353
void Post(const parser::OpenMPConstruct &omp) {
54-
currentConstruct = nullptr;
54+
if (isOpenMPPrivatizingConstruct(omp))
55+
constructs.pop_back();
5556
}
5657

5758
void Post(const parser::Name &name) {
58-
symDefMap.try_emplace(name.symbol, currentConstruct);
59+
auto *current = !constructs.empty() ? constructs.back() : nullptr;
60+
symDefMap.try_emplace(name.symbol, current);
5961
}
6062

61-
const parser::OpenMPConstruct *currentConstruct = nullptr;
63+
llvm::SmallVector<const parser::OpenMPConstruct *> constructs;
6264
llvm::DenseMap<semantics::Symbol *, const parser::OpenMPConstruct *>
6365
symDefMap;
6466

@@ -113,6 +115,9 @@ class DataSharingProcessor {
113115
mlir::OpBuilder::InsertPoint *lastPrivIP);
114116
void insertDeallocs();
115117

118+
static bool isOpenMPPrivatizingConstruct(const parser::OpenMPConstruct &omp);
119+
bool isOpenMPPrivatizingEvaluation(const pft::Evaluation &eval) const;
120+
116121
public:
117122
DataSharingProcessor(lower::AbstractConverter &converter,
118123
semantics::SemanticsContext &semaCtx,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! Testcase adopted from the Fujitsu test suite:
2+
! https://github.com/fujitsu/compiler-test-suite/blob/main/Fortran/0407/0407_0006.f90
3+
4+
!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s
5+
6+
! Make sure that the variable in the atomic construct is privatized at
7+
! the task level
8+
9+
!CHECK: omp.task private(@_QFfredEprv_firstprivate_i32 %{{[0-9]+}}#0 -> %arg0
10+
!CHECK: %[[DECL:[0-9]+]]:2 = hlfir.declare %arg0 {uniq_name = "_QFfredEprv"}
11+
!CHECK: omp.atomic.update %[[DECL]]#0
12+
13+
integer function fred
14+
integer :: prv
15+
16+
prv = 1
17+
!$omp parallel shared(prv)
18+
!$omp task default(firstprivate)
19+
!$omp atomic
20+
prv = prv + 1
21+
!$omp end task
22+
!$omp end parallel
23+
fred = prv
24+
end
25+

flang/test/Lower/OpenMP/sections-predetermined-private.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
end
1212
! CHECK-LABEL: func.func @_QQmain() {
1313
! CHECK: omp.parallel {
14-
! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", pinned}
14+
! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFEi"}
1515
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
1616
! CHECK: omp.sections {
1717
! CHECK: omp.section {

0 commit comments

Comments
 (0)