Skip to content

Commit 444e16f

Browse files
committed
Fix bug when used with lastprivate
Arrays are boxed and those boxed arrays are passed by reference. This can cause problems if we try to perform eager privatization (e.g. lastprivate) on a variable already privatized using delayed privatization. Work around this by loading the reference to the box.
1 parent c955ae4 commit 444e16f

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "flang/Lower/ConvertVariable.h"
1818
#include "flang/Lower/PFTBuilder.h"
1919
#include "flang/Lower/SymbolMap.h"
20+
#include "flang/Optimizer/Builder/BoxValue.h"
2021
#include "flang/Optimizer/Builder/HLFIRTools.h"
2122
#include "flang/Optimizer/Builder/Todo.h"
2223
#include "flang/Optimizer/HLFIR/HLFIROps.h"
@@ -94,8 +95,60 @@ void DataSharingProcessor::insertDeallocs() {
9495

9596
void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) {
9697
bool isFirstPrivate = sym->test(semantics::Symbol::Flag::OmpFirstPrivate);
97-
bool success = converter.createHostAssociateVarClone(
98-
*sym, /*skipDefaultInit=*/isFirstPrivate);
98+
99+
// If we are doing eager-privatization on a symbol created using delayed
100+
// privatization there could be incompatible types here e.g.
101+
// fir.ref<fir.box<fir.array<>>>
102+
bool success = false;
103+
[&]() {
104+
const auto *details =
105+
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
106+
assert(details && "No host-association found");
107+
const Fortran::semantics::Symbol &hsym = details->symbol();
108+
mlir::Value addr = converter.getSymbolAddress(hsym);
109+
110+
if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(addr.getType())) {
111+
if (auto boxTy = mlir::dyn_cast<fir::BoxType>(refTy.getElementType())) {
112+
if (auto arrayTy =
113+
mlir::dyn_cast<fir::SequenceType>(boxTy.getElementType())) {
114+
// FirConverter/fir::ExtendedValue considers all references to boxes
115+
// as mutable boxes. Outside of OpenMP it doesn't make sense to have a
116+
// mutable box of an array. Work around this here by loading the
117+
// reference so it is a normal boxed array.
118+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
119+
mlir::Location loc = converter.genLocation(hsym.name());
120+
fir::ExtendedValue hexv = converter.getSymbolExtendedValue(hsym);
121+
122+
llvm::SmallVector<mlir::Value> extents =
123+
fir::factory::getExtents(loc, builder, hexv);
124+
125+
// TODO: uniqName, name
126+
mlir::Value allocVal =
127+
builder.allocateLocal(loc, arrayTy, /*uniqName=*/"",
128+
/*name=*/"", extents, /*typeParams=*/{},
129+
sym->GetUltimate().attrs().test(
130+
Fortran::semantics::Attr::TARGET));
131+
mlir::Value shape = builder.genShape(loc, extents);
132+
mlir::Value box = builder.createBox(loc, boxTy, allocVal, shape,
133+
nullptr, {}, nullptr);
134+
135+
// This can't be a CharArrayBoxValue because otherwise
136+
// boxTy.getElementType() would be a charcater type.
137+
// Assume the array element type isn't polymorphic because we are
138+
// privatizing.
139+
fir::ExtendedValue newExv = fir::ArrayBoxValue{box, extents};
140+
141+
converter.bindSymbol(*sym, newExv);
142+
success = true;
143+
return;
144+
}
145+
}
146+
}
147+
148+
// Normal case:
149+
success = converter.createHostAssociateVarClone(
150+
*sym, /*skipDefaultInit=*/isFirstPrivate);
151+
}();
99152
(void)success;
100153
assert(success && "Privatization failed due to existing binding");
101154

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s
2+
! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s
3+
4+
! Check that we can lower this without crashing
5+
6+
! CHECK: func.func @_QPlastprivate_of_private
7+
subroutine lastprivate_of_private(a)
8+
real :: a(100)
9+
integer i
10+
! CHECK: omp.parallel private({{.*}}) {
11+
!$omp parallel private(a)
12+
! CHECK: omp.parallel {
13+
!$omp parallel shared(a)
14+
! CHECK: omp.wsloop {
15+
!$omp do lastprivate(a)
16+
! CHECK: omp.loop_nest
17+
do i=1,100
18+
a(i) = 1.0
19+
end do
20+
!$omp end parallel
21+
!$omp end parallel
22+
end subroutine

0 commit comments

Comments
 (0)