Skip to content

Commit 6c67544

Browse files
committed
[flang][MLIR][OpenMP] Extend delayed privatization for scalar allocatables
One more step in extending support for delayed privatization. This diff adds support for scalar allocatables.
1 parent 1dd104d commit 6c67544

File tree

5 files changed

+103
-13
lines changed

5 files changed

+103
-13
lines changed

flang/include/flang/Optimizer/Builder/BoxValue.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,17 @@ class ExtendedValue : public details::matcher<ExtendedValue> {
535535

536536
const VT &matchee() const { return box; }
537537

538+
/// Clone an ExtendedValue to a new instance changing the base address.
539+
///
540+
/// TODO So far, this is only a shallow clone; only the base address is
541+
/// replaced. This will probably be extended to implement deep cloning to
542+
/// support scenarios such as delayed privatization for ArrayBoxValue's.
543+
ExtendedValue clone(mlir::Value newBase) const {
544+
return match(
545+
[&](const UnboxedValue &box) -> ExtendedValue { return newBase; },
546+
[&](const auto &box) -> ExtendedValue { return box.clone(newBase); });
547+
}
548+
538549
private:
539550
VT box;
540551
};

flang/lib/Lower/Bridge.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
748748

749749
void copyVar(mlir::Location loc, mlir::Value dst,
750750
mlir::Value src) override final {
751-
copyVarHLFIR(loc, dst, src);
751+
copyVarHLFIR(loc, Fortran::lower::SymbolBox::Intrinsic{dst},
752+
Fortran::lower::SymbolBox::Intrinsic{src});
752753
}
753754

754755
void copyHostAssociateVar(
@@ -1009,10 +1010,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
10091010
// `omp.private`'s `alloc` block. If this is the case, we return this
10101011
// `SymbolBox::Intrinsic` value.
10111012
if (Fortran::lower::SymbolBox v = symMap->lookupSymbol(sym))
1012-
return v.match(
1013-
[&](const Fortran::lower::SymbolBox::Intrinsic &)
1014-
-> Fortran::lower::SymbolBox { return v; },
1015-
[](const auto &) -> Fortran::lower::SymbolBox { return {}; });
1013+
return v;
10161014

10171015
return {};
10181016
}
@@ -1060,15 +1058,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
10601058
const Fortran::lower::SymbolBox &rhs_sb) {
10611059
mlir::Location loc = genLocation(sym.name());
10621060
if (lowerToHighLevelFIR())
1063-
copyVarHLFIR(loc, lhs_sb.getAddr(), rhs_sb.getAddr());
1061+
copyVarHLFIR(loc, lhs_sb, rhs_sb);
10641062
else
10651063
copyVarFIR(loc, sym, lhs_sb, rhs_sb);
10661064
}
10671065

1068-
void copyVarHLFIR(mlir::Location loc, mlir::Value dst, mlir::Value src) {
1066+
void copyVarHLFIR(mlir::Location loc, Fortran::lower::SymbolBox dst,
1067+
Fortran::lower::SymbolBox src) {
10691068
assert(lowerToHighLevelFIR());
1070-
hlfir::Entity lhs{dst};
1071-
hlfir::Entity rhs{src};
1069+
hlfir::Entity lhs{dst.getAddr()};
1070+
hlfir::Entity rhs{src.getAddr()};
10721071
// Temporary_lhs is set to true in hlfir.assign below to avoid user
10731072
// assignment to be used and finalization to be called on the LHS.
10741073
// This may or may not be correct but mimics the current behaviour
@@ -1082,7 +1081,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
10821081
/*keepLhsLengthInAllocatableAssignment=*/false,
10831082
/*temporary_lhs=*/true);
10841083
};
1085-
if (lhs.isAllocatable()) {
1084+
1085+
bool isBoxAllocatable = dst.match(
1086+
[](const fir::MutableBoxValue &box) { return box.isAllocatable(); },
1087+
[](const auto &box) { return false; });
1088+
1089+
if (isBoxAllocatable) {
10861090
// Deep copy allocatable if it is allocated.
10871091
// Note that when allocated, the RHS is already allocated with the LHS
10881092
// shape for copy on entry in createHostAssociateVarClone.

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) {
5050
}
5151

5252
void DataSharingProcessor::insertDeallocs() {
53+
// TODO Extend delayed privatization to include a `dealloc` region?
5354
for (const Fortran::semantics::Symbol *sym : privatizedSymbols)
5455
if (Fortran::semantics::IsAllocatable(sym->GetUltimate())) {
5556
converter.createHostAssociateVarCloneDealloc(*sym);
@@ -376,6 +377,7 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
376377
symLoc, uniquePrivatizerName, symType,
377378
isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate
378379
: mlir::omp::DataSharingClauseType::Private);
380+
fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym);
379381

380382
symTable->pushScope();
381383

@@ -386,7 +388,7 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
386388
&allocRegion, /*insertPt=*/{}, symType, symLoc);
387389

388390
firOpBuilder.setInsertionPointToEnd(allocEntryBlock);
389-
symTable->addSymbol(*sym, allocRegion.getArgument(0));
391+
symTable->addSymbol(*sym, symExV.clone(allocRegion.getArgument(0)));
390392
symTable->pushScope();
391393
cloneSymbol(sym);
392394
firOpBuilder.create<mlir::omp::YieldOp>(
@@ -403,10 +405,10 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
403405
mlir::Block *copyEntryBlock = firOpBuilder.createBlock(
404406
&copyRegion, /*insertPt=*/{}, {symType, symType}, {symLoc, symLoc});
405407
firOpBuilder.setInsertionPointToEnd(copyEntryBlock);
406-
symTable->addSymbol(*sym, copyRegion.getArgument(0),
408+
symTable->addSymbol(*sym, symExV.clone(copyRegion.getArgument(0)),
407409
/*force=*/true);
408410
symTable->pushScope();
409-
symTable->addSymbol(*sym, copyRegion.getArgument(1));
411+
symTable->addSymbol(*sym, symExV.clone(copyRegion.getArgument(1)));
410412
auto ip = firOpBuilder.saveInsertionPoint();
411413
copyFirstPrivateSymbol(sym, &ip);
412414

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
! Test delayed privatization for allocatables: `firstprivate`.
2+
3+
! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s
4+
5+
subroutine delayed_privatization_allocatable
6+
implicit none
7+
integer, allocatable :: var1
8+
9+
!$omp parallel firstprivate(var1)
10+
var1 = 10
11+
!$omp end parallel
12+
end subroutine
13+
14+
! CHECK-LABEL: omp.private {type = firstprivate}
15+
! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<i32>>>]] alloc {
16+
17+
! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
18+
19+
! CHECK: } copy {
20+
! CHECK: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]):
21+
22+
! CHECK-NEXT: %[[PRIV_BASE_VAL:.*]] = fir.load %[[PRIV_PRIV_ARG]]
23+
! CHECK-NEXT: %[[PRIV_BASE_BOX:.*]] = fir.box_addr %[[PRIV_BASE_VAL]]
24+
! CHECK-NEXT: %[[PRIV_BASE_ADDR:.*]] = fir.convert %[[PRIV_BASE_BOX]]
25+
! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
26+
! CHECK-NEXT: %[[COPY_COND:.*]] = arith.cmpi ne, %[[PRIV_BASE_ADDR]], %[[C0]] : i64
27+
28+
! CHECK-NEXT: fir.if %[[COPY_COND]] {
29+
! CHECK-NEXT: %[[ORIG_BASE_VAL:.*]] = fir.load %[[PRIV_ORIG_ARG]]
30+
! CHECK-NEXT: %[[ORIG_BASE_ADDR:.*]] = fir.box_addr %[[ORIG_BASE_VAL]]
31+
! CHECK-NEXT: %[[ORIG_BASE_LD:.*]] = fir.load %[[ORIG_BASE_ADDR]]
32+
! CHECK-NEXT: hlfir.assign %[[ORIG_BASE_LD]] to %[[PRIV_BASE_BOX]] temporary_lhs
33+
! CHECK-NEXT: }
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
! Test delayed privatization for allocatables: `private`.
2+
3+
! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s
4+
5+
subroutine delayed_privatization_allocatable
6+
implicit none
7+
integer, allocatable :: var1
8+
9+
!$omp parallel private(var1)
10+
var1 = 10
11+
!$omp end parallel
12+
end subroutine
13+
14+
! CHECK-LABEL: omp.private {type = private}
15+
! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<i32>>>]] alloc {
16+
17+
! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
18+
19+
! CHECK-NEXT: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_allocatableEvar1"}
20+
21+
! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : !fir.ref<!fir.box<!fir.heap<i32>>>
22+
! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
23+
! CHECK-NEXT: %[[PRIV_ARG_ADDR:.*]] = fir.convert %[[PRIV_ARG_BOX]] : (!fir.heap<i32>) -> i64
24+
! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
25+
! CHECK-NEXT: %[[ALLOC_COND:.*]] = arith.cmpi ne, %[[PRIV_ARG_ADDR]], %[[C0]] : i64
26+
27+
! CHECK-NEXT: fir.if %[[ALLOC_COND]] {
28+
! CHECK-NEXT: %[[PRIV_ALLOCMEM:.*]] = fir.allocmem i32 {fir.must_be_heap = true, uniq_name = "_QFdelayed_privatization_allocatableEvar1.alloc"}
29+
! CHECK-NEXT: %[[PRIV_ALLOCMEM_BOX:.*]] = fir.embox %[[PRIV_ALLOCMEM]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>>
30+
! CHECK-NEXT: fir.store %[[PRIV_ALLOCMEM_BOX]] to %[[PRIV_ALLOC]] : !fir.ref<!fir.box<!fir.heap<i32>>>
31+
! CHECK-NEXT: } else {
32+
! CHECK-NEXT: %[[ZERO_BITS:.*]] = fir.zero_bits !fir.heap<i32>
33+
! CHECK-NEXT: %[[ZERO_BOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>>
34+
! CHECK-NEXT: fir.store %[[ZERO_BOX]] to %[[PRIV_ALLOC]] : !fir.ref<!fir.box<!fir.heap<i32>>>
35+
! CHECK-NEXT: }
36+
37+
! CHECK-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOC]]
38+
! CHECK-NEXT: omp.yield(%[[PRIV_DECL]]#0 : [[TYPE]])
39+
40+
! CHECK-NEXT: }

0 commit comments

Comments
 (0)