Skip to content

Commit 98ffdf3

Browse files
authored
[flang][OpenMP] Don't privatize pre-determined symbols declare by nested BLOCKs (#152652)
Fixes a bug when a block variable is marked as pre-determined private. In such case, we can simply ignore privatizing that symbol within the context of the currrent OpenMP construct since the "private" allocation for the symbol will be emitted within the nested block anyway.
1 parent 818ee8f commit 98ffdf3

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ namespace lower {
3636
namespace omp {
3737
bool DataSharingProcessor::OMPConstructSymbolVisitor::isSymbolDefineBy(
3838
const semantics::Symbol *symbol, lower::pft::Evaluation &eval) const {
39-
return eval.visit(
40-
common::visitors{[&](const parser::OpenMPConstruct &functionParserNode) {
41-
return symDefMap.count(symbol) &&
42-
symDefMap.at(symbol) == &functionParserNode;
43-
},
44-
[](const auto &functionParserNode) { return false; }});
39+
return eval.visit(common::visitors{
40+
[&](const parser::OpenMPConstruct &functionParserNode) {
41+
return symDefMap.count(symbol) &&
42+
symDefMap.at(symbol) == ConstructPtr(&functionParserNode);
43+
},
44+
[](const auto &functionParserNode) { return false; }});
4545
}
4646

4747
static bool isConstructWithTopLevelTarget(lower::pft::Evaluation &eval) {
@@ -553,8 +553,16 @@ void DataSharingProcessor::collectSymbols(
553553
return sym->test(semantics::Symbol::Flag::OmpImplicit);
554554
}
555555

556-
if (collectPreDetermined)
557-
return sym->test(semantics::Symbol::Flag::OmpPreDetermined);
556+
if (collectPreDetermined) {
557+
// Collect pre-determined symbols only if they are defined by the current
558+
// OpenMP evaluation. If `sym` is not defined by the current OpenMP
559+
// evaluation then it is defined by a block nested within the OpenMP
560+
// construct. This, in turn, means that the private allocation for the
561+
// symbol will be emitted as part of the nested block and there is no need
562+
// to privatize it within the OpenMP construct.
563+
return visitor.isSymbolDefineBy(sym, eval) &&
564+
sym->test(semantics::Symbol::Flag::OmpPreDetermined);
565+
}
558566

559567
return !sym->test(semantics::Symbol::Flag::OmpImplicit) &&
560568
!sym->test(semantics::Symbol::Flag::OmpPreDetermined);

flang/lib/Lower/OpenMP/DataSharingProcessor.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "flang/Parser/parse-tree.h"
2020
#include "flang/Semantics/symbol.h"
2121
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
22+
#include <variant>
2223

2324
namespace mlir {
2425
namespace omp {
@@ -58,20 +59,30 @@ class DataSharingProcessor {
5859
}
5960

6061
void Post(const parser::Name &name) {
61-
auto *current = !constructs.empty() ? constructs.back() : nullptr;
62+
auto current = !constructs.empty() ? constructs.back() : ConstructPtr();
6263
symDefMap.try_emplace(name.symbol, current);
6364
}
6465

65-
llvm::SmallVector<const parser::OpenMPConstruct *> constructs;
66-
llvm::DenseMap<semantics::Symbol *, const parser::OpenMPConstruct *>
67-
symDefMap;
66+
bool Pre(const parser::DeclarationConstruct &decl) {
67+
constructs.push_back(&decl);
68+
return true;
69+
}
70+
71+
void Post(const parser::DeclarationConstruct &decl) {
72+
constructs.pop_back();
73+
}
6874

6975
/// Given a \p symbol and an \p eval, returns true if eval is the OMP
7076
/// construct that defines symbol.
7177
bool isSymbolDefineBy(const semantics::Symbol *symbol,
7278
lower::pft::Evaluation &eval) const;
7379

7480
private:
81+
using ConstructPtr = std::variant<const parser::OpenMPConstruct *,
82+
const parser::DeclarationConstruct *>;
83+
llvm::SmallVector<ConstructPtr> constructs;
84+
llvm::DenseMap<semantics::Symbol *, ConstructPtr> symDefMap;
85+
7586
unsigned version;
7687
};
7788

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
! Fixes a bug when a block variable is marked as pre-determined private. In such
2+
! case, we can simply ignore privatizing that symbol within the context of the
3+
! currrent OpenMP construct since the "private" allocation for the symbol will
4+
! be emitted within the nested block anyway.
5+
6+
! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
7+
8+
subroutine block_predetermined_privatization
9+
implicit none
10+
integer :: i
11+
12+
!$omp parallel
13+
do i=1,10
14+
block
15+
integer :: j
16+
do j=1,10
17+
end do
18+
end block
19+
end do
20+
!$omp end parallel
21+
end subroutine
22+
23+
! CHECK-LABEL: func.func @_QPblock_predetermined_privatization() {
24+
! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "{{.*}}Ei"}
25+
! CHECK: omp.parallel private(@{{.*}}Ei_private_i32 %[[I_DECL]]#0 -> %{{.*}} : !fir.ref<i32>) {
26+
! CHECK: fir.do_loop {{.*}} {
27+
! Verify that `j` is allocated whithin the same scope of its block (i.e. inside
28+
! the `parallel` loop).
29+
! CHECK: fir.alloca i32 {bindc_name = "j", {{.*}}}
30+
! CHECK: }
31+
! CHECK: }
32+
! CHECK: }

0 commit comments

Comments
 (0)