Skip to content

Commit a4aac22

Browse files
authored
[Flang][OpenMp] Fix to threadprivate not working with host-association. (#74966)
This patch considers host-associated variables to generate threadprivate Ops. Fixes: #60763 #84561
1 parent f8fab21 commit a4aac22

File tree

4 files changed

+111
-7
lines changed

4 files changed

+111
-7
lines changed

flang/lib/Lower/HostAssociations.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flang/Lower/CallInterface.h"
1515
#include "flang/Lower/ConvertType.h"
1616
#include "flang/Lower/ConvertVariable.h"
17+
#include "flang/Lower/OpenMP.h"
1718
#include "flang/Lower/PFTBuilder.h"
1819
#include "flang/Lower/SymbolMap.h"
1920
#include "flang/Optimizer/Builder/Character.h"
@@ -542,7 +543,10 @@ void Fortran::lower::HostAssociations::addSymbolsToBind(
542543
"must be initially empty");
543544
this->hostScope = &hostScope;
544545
for (const auto *s : symbols)
545-
if (Fortran::lower::symbolIsGlobal(*s)) {
546+
// GlobalOp are created for non-global threadprivate variable,
547+
// so considering them as globals.
548+
if (Fortran::lower::symbolIsGlobal(*s) ||
549+
(*s).test(Fortran::semantics::Symbol::Flag::OmpThreadprivate)) {
546550
// The ultimate symbol is stored here so that global symbols from the
547551
// host scope can later be searched in this set.
548552
globalSymbols.insert(&s->GetUltimate());
@@ -590,9 +594,15 @@ void Fortran::lower::HostAssociations::internalProcedureBindings(
590594
for (auto &hostVariable : pft::getScopeVariableList(*hostScope))
591595
if ((hostVariable.isAggregateStore() && hostVariable.isGlobal()) ||
592596
(hostVariable.hasSymbol() &&
593-
globalSymbols.contains(&hostVariable.getSymbol().GetUltimate())))
597+
globalSymbols.contains(&hostVariable.getSymbol().GetUltimate()))) {
594598
Fortran::lower::instantiateVariable(converter, hostVariable, symMap,
595599
storeMap);
600+
// Generate threadprivate Op for host associated variables.
601+
if (hostVariable.hasSymbol() &&
602+
hostVariable.getSymbol().test(
603+
Fortran::semantics::Symbol::Flag::OmpThreadprivate))
604+
Fortran::lower::genThreadprivateOp(converter, hostVariable);
605+
}
596606
}
597607
if (tupleSymbols.empty())
598608
return;

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,10 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
170170
};
171171

172172
llvm::SetVector<const Fortran::semantics::Symbol *> threadprivateSyms;
173-
converter.collectSymbolSet(
174-
eval, threadprivateSyms,
175-
Fortran::semantics::Symbol::Flag::OmpThreadprivate);
173+
converter.collectSymbolSet(eval, threadprivateSyms,
174+
Fortran::semantics::Symbol::Flag::OmpThreadprivate,
175+
/*collectSymbols=*/true,
176+
/*collectHostAssociatedSymbols=*/true);
176177
std::set<Fortran::semantics::SourceName> threadprivateSymNames;
177178

178179
// For a COMMON block, the ThreadprivateOp is generated for itself instead of
@@ -2276,8 +2277,15 @@ void Fortran::lower::genThreadprivateOp(
22762277
// variable in main program, and it has implicit SAVE attribute. Take it as
22772278
// with SAVE attribute, so to create GlobalOp for it to simplify the
22782279
// translation to LLVM IR.
2279-
fir::GlobalOp global = globalInitialization(converter, firOpBuilder, sym,
2280-
var, currentLocation);
2280+
// Avoids performing multiple globalInitializations.
2281+
fir::GlobalOp global;
2282+
auto module = converter.getModuleOp();
2283+
std::string globalName = converter.mangleName(sym);
2284+
if (module.lookupSymbol<fir::GlobalOp>(globalName))
2285+
global = module.lookupSymbol<fir::GlobalOp>(globalName);
2286+
else
2287+
global = globalInitialization(converter, firOpBuilder, sym, var,
2288+
currentLocation);
22812289

22822290
mlir::Value symValue = firOpBuilder.create<fir::AddrOfOp>(
22832291
currentLocation, global.resultType(), global.getSymbol());
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
! This test checks lowering of OpenMP Threadprivate Directive.
2+
! Test for threadprivate variable in host association.
3+
4+
!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
5+
6+
!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
7+
!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
8+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
9+
!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
10+
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
11+
!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
12+
!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
13+
!CHECK: return
14+
!CHECK: }
15+
!CHECK: func.func private @_QFPsub() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage<internal>} {
16+
!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
17+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
18+
!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
19+
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
20+
!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
21+
!CHECK: omp.parallel {
22+
!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
23+
!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
24+
!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
25+
!CHECK: omp.terminator
26+
!CHECK: }
27+
!CHECK: return
28+
!CHECK: }
29+
!CHECK: fir.global internal @_QFEa : i32 {
30+
!CHECK: %[[A:.*]] = fir.undefined i32
31+
!CHECK: fir.has_value %[[A]] : i32
32+
!CHECK: }
33+
34+
program main
35+
integer :: a
36+
!$omp threadprivate(a)
37+
call sub()
38+
contains
39+
subroutine sub()
40+
!$omp parallel
41+
print *, a
42+
!$omp end parallel
43+
end
44+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
! This test checks lowering of OpenMP Threadprivate Directive.
2+
! Test for threadprivate variable in host association.
3+
4+
!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
5+
6+
!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
7+
!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
8+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
9+
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
10+
!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
11+
!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
12+
!CHECK: return
13+
!CHECK: }
14+
!CHECK: func.func private @_QFPsub() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage<internal>} {
15+
!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
16+
!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
17+
!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
18+
!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
19+
!CHECK: omp.parallel {
20+
!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
21+
!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
22+
!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
23+
!CHECK: omp.terminator
24+
!CHECK: }
25+
!CHECK: return
26+
!CHECK: }
27+
!CHECK: fir.global internal @_QFEa : i32 {
28+
!CHECK: %[[A:.*]] = fir.zero_bits i32
29+
!CHECK: fir.has_value %[[A]] : i32
30+
!CHECK: }
31+
32+
program main
33+
integer, save :: a
34+
!$omp threadprivate(a)
35+
call sub()
36+
contains
37+
subroutine sub()
38+
!$omp parallel
39+
print *, a
40+
!$omp end parallel
41+
end
42+
end

0 commit comments

Comments
 (0)