[flang-commits] [flang] [Flang][OpenMp] Fix to threadprivate not working with host-association. (PR #74966)
via flang-commits
flang-commits at lists.llvm.org
Mon Dec 11 20:55:36 PST 2023
https://github.com/harishch4 updated https://github.com/llvm/llvm-project/pull/74966
>From 8c9ea8010c131b2a484dcee45ef5edf2b4340d8d Mon Sep 17 00:00:00 2001
From: Harish Chambeti <harishcse44 at gmail.com>
Date: Sun, 10 Dec 2023 10:44:18 +0530
Subject: [PATCH 1/2] [Flang][OpenMp] Fix to threadprivate not working with
host-association.
---
flang/lib/Lower/HostAssociations.cpp | 14 +++++-
flang/lib/Lower/OpenMP.cpp | 17 +++++--
.../threadprivate-host-association-2.f90 | 44 +++++++++++++++++++
.../OpenMP/threadprivate-host-association.f90 | 42 ++++++++++++++++++
4 files changed, 112 insertions(+), 5 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
create mode 100644 flang/test/Lower/OpenMP/threadprivate-host-association.f90
diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp
index a62f7a7e99b6ff..e2a403f111301f 100644
--- a/flang/lib/Lower/HostAssociations.cpp
+++ b/flang/lib/Lower/HostAssociations.cpp
@@ -16,6 +16,7 @@
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/SymbolMap.h"
+#include "flang/Lower/OpenMP.h"
#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Todo.h"
@@ -508,7 +509,10 @@ void Fortran::lower::HostAssociations::addSymbolsToBind(
"must be initially empty");
this->hostScope = &hostScope;
for (const auto *s : symbols)
- if (Fortran::lower::symbolIsGlobal(*s)) {
+ // GlobalOp are created for non-global threadprivate variable,
+ // so considering them as globals.
+ if (Fortran::lower::symbolIsGlobal(*s) ||
+ (*s).test(Fortran::semantics::Symbol::Flag::OmpThreadprivate)) {
// The ultimate symbol is stored here so that global symbols from the
// host scope can later be searched in this set.
globalSymbols.insert(&s->GetUltimate());
@@ -556,9 +560,15 @@ void Fortran::lower::HostAssociations::internalProcedureBindings(
for (auto &hostVariable : pft::getScopeVariableList(*hostScope))
if ((hostVariable.isAggregateStore() && hostVariable.isGlobal()) ||
(hostVariable.hasSymbol() &&
- globalSymbols.contains(&hostVariable.getSymbol().GetUltimate())))
+ globalSymbols.contains(&hostVariable.getSymbol().GetUltimate()))) {
Fortran::lower::instantiateVariable(converter, hostVariable, symMap,
storeMap);
+ // Generate threadprivate Op for host associated variables.
+ if (hostVariable.hasSymbol() &&
+ hostVariable.getSymbol().test(
+ Fortran::semantics::Symbol::Flag::OmpThreadprivate))
+ Fortran::lower::genThreadprivateOp(converter, hostVariable);
+ }
}
if (tupleSymbols.empty())
return;
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index eeba87fcd15116..ba07d015de39cb 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -1996,9 +1996,12 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
};
llvm::SetVector<const Fortran::semantics::Symbol *> threadprivateSyms;
+ // Considering Host associated symbols as well.
converter.collectSymbolSet(
eval, threadprivateSyms,
- Fortran::semantics::Symbol::Flag::OmpThreadprivate);
+ Fortran::semantics::Symbol::Flag::OmpThreadprivate,
+ /*collectSymbols=*/true,
+ /*collectHostAssociatedSymbols=*/true);
std::set<Fortran::semantics::SourceName> threadprivateSymNames;
// For a COMMON block, the ThreadprivateOp is generated for itself instead of
@@ -3528,8 +3531,16 @@ void Fortran::lower::genThreadprivateOp(
// variable in main program, and it has implicit SAVE attribute. Take it as
// with SAVE attribute, so to create GlobalOp for it to simplify the
// translation to LLVM IR.
- fir::GlobalOp global = globalInitialization(converter, firOpBuilder, sym,
- var, currentLocation);
+ fir::GlobalOp global;
+ // Avoids performing multiple globalInitializations.
+ auto module = converter.getModuleOp();
+ std::string globalName = converter.mangleName(sym);
+ if (module.lookupSymbol<fir::GlobalOp>(globalName)) {
+ global = module.lookupSymbol<fir::GlobalOp>(globalName);
+ } else {
+ global = globalInitialization(converter, firOpBuilder, sym, var,
+ currentLocation);
+ }
mlir::Value symValue = firOpBuilder.create<fir::AddrOfOp>(
currentLocation, global.resultType(), global.getSymbol());
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
new file mode 100644
index 00000000000000..e6f9a69333da1b
--- /dev/null
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
@@ -0,0 +1,44 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable in host association.
+
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
+!CHECK: return
+!CHECK: }
+!CHECK: func.func @_QFPsub() attributes {fir.internal_proc} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: omp.parallel {
+!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
+!CHECK: omp.terminator
+!CHECK: }
+!CHECK: return
+!CHECK: }
+!CHECK: fir.global internal @_QFEa : i32 {
+!CHECK: %[[A:.*]] = fir.undefined i32
+!CHECK: fir.has_value %[[A]] : i32
+!CHECK: }
+
+program main
+ integer :: a
+ !$omp threadprivate(a)
+ call sub()
+contains
+ subroutine sub()
+ !$omp parallel
+ print *, a
+ !$omp end parallel
+ end
+end
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association.f90
new file mode 100644
index 00000000000000..bb6d58b0ff2189
--- /dev/null
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association.f90
@@ -0,0 +1,42 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable in host association.
+
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
+!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
+!CHECK: return
+!CHECK: }
+!CHECK: func.func @_QFPsub() attributes {fir.internal_proc} {
+!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: omp.parallel {
+!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
+!CHECK: omp.terminator
+!CHECK: }
+!CHECK: return
+!CHECK: }
+!CHECK: fir.global internal @_QFEa : i32 {
+!CHECK: %[[A:.*]] = fir.zero_bits i32
+!CHECK: fir.has_value %[[A]] : i32
+!CHECK: }
+
+program main
+ integer, save :: a
+ !$omp threadprivate(a)
+ call sub()
+contains
+ subroutine sub()
+ !$omp parallel
+ print *, a
+ !$omp end parallel
+ end
+end
>From 520d8d55dc3c7bfabad030b278284ba5a6f90974 Mon Sep 17 00:00:00 2001
From: Harish Chambeti <harishcse44 at gmail.com>
Date: Sun, 10 Dec 2023 10:44:18 +0530
Subject: [PATCH 2/2] [Flang][OpenMp] Fix to threadprivate not working with
host-association.
---
flang/lib/Lower/HostAssociations.cpp | 14 +++++-
flang/lib/Lower/OpenMP.cpp | 20 ++++++---
.../threadprivate-host-association-2.f90 | 44 +++++++++++++++++++
.../OpenMP/threadprivate-host-association.f90 | 42 ++++++++++++++++++
4 files changed, 113 insertions(+), 7 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
create mode 100644 flang/test/Lower/OpenMP/threadprivate-host-association.f90
diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp
index a62f7a7e99b6ff..e2a403f111301f 100644
--- a/flang/lib/Lower/HostAssociations.cpp
+++ b/flang/lib/Lower/HostAssociations.cpp
@@ -16,6 +16,7 @@
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/SymbolMap.h"
+#include "flang/Lower/OpenMP.h"
#include "flang/Optimizer/Builder/Character.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Todo.h"
@@ -508,7 +509,10 @@ void Fortran::lower::HostAssociations::addSymbolsToBind(
"must be initially empty");
this->hostScope = &hostScope;
for (const auto *s : symbols)
- if (Fortran::lower::symbolIsGlobal(*s)) {
+ // GlobalOp are created for non-global threadprivate variable,
+ // so considering them as globals.
+ if (Fortran::lower::symbolIsGlobal(*s) ||
+ (*s).test(Fortran::semantics::Symbol::Flag::OmpThreadprivate)) {
// The ultimate symbol is stored here so that global symbols from the
// host scope can later be searched in this set.
globalSymbols.insert(&s->GetUltimate());
@@ -556,9 +560,15 @@ void Fortran::lower::HostAssociations::internalProcedureBindings(
for (auto &hostVariable : pft::getScopeVariableList(*hostScope))
if ((hostVariable.isAggregateStore() && hostVariable.isGlobal()) ||
(hostVariable.hasSymbol() &&
- globalSymbols.contains(&hostVariable.getSymbol().GetUltimate())))
+ globalSymbols.contains(&hostVariable.getSymbol().GetUltimate()))) {
Fortran::lower::instantiateVariable(converter, hostVariable, symMap,
storeMap);
+ // Generate threadprivate Op for host associated variables.
+ if (hostVariable.hasSymbol() &&
+ hostVariable.getSymbol().test(
+ Fortran::semantics::Symbol::Flag::OmpThreadprivate))
+ Fortran::lower::genThreadprivateOp(converter, hostVariable);
+ }
}
if (tupleSymbols.empty())
return;
diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index eeba87fcd15116..a6c4b8a1445893 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -1996,9 +1996,11 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter,
};
llvm::SetVector<const Fortran::semantics::Symbol *> threadprivateSyms;
- converter.collectSymbolSet(
- eval, threadprivateSyms,
- Fortran::semantics::Symbol::Flag::OmpThreadprivate);
+ // Considering Host associated symbols as well.
+ converter.collectSymbolSet(eval, threadprivateSyms,
+ Fortran::semantics::Symbol::Flag::OmpThreadprivate,
+ /*collectSymbols=*/true,
+ /*collectHostAssociatedSymbols=*/true);
std::set<Fortran::semantics::SourceName> threadprivateSymNames;
// For a COMMON block, the ThreadprivateOp is generated for itself instead of
@@ -3528,8 +3530,16 @@ void Fortran::lower::genThreadprivateOp(
// variable in main program, and it has implicit SAVE attribute. Take it as
// with SAVE attribute, so to create GlobalOp for it to simplify the
// translation to LLVM IR.
- fir::GlobalOp global = globalInitialization(converter, firOpBuilder, sym,
- var, currentLocation);
+ fir::GlobalOp global;
+ // Avoids performing multiple globalInitializations.
+ auto module = converter.getModuleOp();
+ std::string globalName = converter.mangleName(sym);
+ if (module.lookupSymbol<fir::GlobalOp>(globalName)) {
+ global = module.lookupSymbol<fir::GlobalOp>(globalName);
+ } else {
+ global = globalInitialization(converter, firOpBuilder, sym, var,
+ currentLocation);
+ }
mlir::Value symValue = firOpBuilder.create<fir::AddrOfOp>(
currentLocation, global.resultType(), global.getSymbol());
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
new file mode 100644
index 00000000000000..e6f9a69333da1b
--- /dev/null
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90
@@ -0,0 +1,44 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable in host association.
+
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
+!CHECK: return
+!CHECK: }
+!CHECK: func.func @_QFPsub() attributes {fir.internal_proc} {
+!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"}
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: omp.parallel {
+!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
+!CHECK: omp.terminator
+!CHECK: }
+!CHECK: return
+!CHECK: }
+!CHECK: fir.global internal @_QFEa : i32 {
+!CHECK: %[[A:.*]] = fir.undefined i32
+!CHECK: fir.has_value %[[A]] : i32
+!CHECK: }
+
+program main
+ integer :: a
+ !$omp threadprivate(a)
+ call sub()
+contains
+ subroutine sub()
+ !$omp parallel
+ print *, a
+ !$omp end parallel
+ end
+end
diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association.f90
new file mode 100644
index 00000000000000..bb6d58b0ff2189
--- /dev/null
+++ b/flang/test/Lower/OpenMP/threadprivate-host-association.f90
@@ -0,0 +1,42 @@
+! This test checks lowering of OpenMP Threadprivate Directive.
+! Test for threadprivate variable in host association.
+
+!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} {
+!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: fir.call @_QFPsub() fastmath<contract> : () -> ()
+!CHECK: return
+!CHECK: }
+!CHECK: func.func @_QFPsub() attributes {fir.internal_proc} {
+!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref<i32>
+!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: omp.parallel {
+!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref<i32> -> !fir.ref<i32>
+!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref<i32>
+!CHECK: omp.terminator
+!CHECK: }
+!CHECK: return
+!CHECK: }
+!CHECK: fir.global internal @_QFEa : i32 {
+!CHECK: %[[A:.*]] = fir.zero_bits i32
+!CHECK: fir.has_value %[[A]] : i32
+!CHECK: }
+
+program main
+ integer, save :: a
+ !$omp threadprivate(a)
+ call sub()
+contains
+ subroutine sub()
+ !$omp parallel
+ print *, a
+ !$omp end parallel
+ end
+end
More information about the flang-commits
mailing list