Skip to content

Commit ad6d947

Browse files
committed
[flang] Basic PFT to MLIR lowering for do concurrent locality specifiers
1 parent f73bf74 commit ad6d947

File tree

5 files changed

+157
-25
lines changed

5 files changed

+157
-25
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ class AbstractConverter {
348348
virtual Fortran::lower::SymbolBox
349349
lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) = 0;
350350

351+
virtual Fortran::lower::SymbolBox
352+
shallowLookupSymbol(const Fortran::semantics::Symbol &sym) = 0;
353+
351354
/// Return the mlir::SymbolTable associated to the ModuleOp.
352355
/// Look-ups are faster using it than using module.lookup<>,
353356
/// but the module op should be queried in case of failure

flang/lib/Lower/Bridge.cpp

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#include "flang/Lower/Bridge.h"
1414

15+
#include "OpenMP/DataSharingProcessor.h"
16+
#include "OpenMP/Utils.h"
1517
#include "flang/Lower/Allocatable.h"
1618
#include "flang/Lower/CallInterface.h"
1719
#include "flang/Lower/Coarray.h"
@@ -1144,6 +1146,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
11441146
return name;
11451147
}
11461148

1149+
/// Find the symbol in the inner-most level of the local map or return null.
1150+
Fortran::lower::SymbolBox
1151+
shallowLookupSymbol(const Fortran::semantics::Symbol &sym) override {
1152+
if (Fortran::lower::SymbolBox v = localSymbols.shallowLookupSymbol(sym))
1153+
return v;
1154+
return {};
1155+
}
1156+
11471157
private:
11481158
FirConverter() = delete;
11491159
FirConverter(const FirConverter &) = delete;
@@ -1218,14 +1228,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
12181228
return {};
12191229
}
12201230

1221-
/// Find the symbol in the inner-most level of the local map or return null.
1222-
Fortran::lower::SymbolBox
1223-
shallowLookupSymbol(const Fortran::semantics::Symbol &sym) {
1224-
if (Fortran::lower::SymbolBox v = localSymbols.shallowLookupSymbol(sym))
1225-
return v;
1226-
return {};
1227-
}
1228-
12291231
/// Find the symbol in one level up of symbol map such as for host-association
12301232
/// in OpenMP code or return null.
12311233
Fortran::lower::SymbolBox
@@ -2028,9 +2030,31 @@ class FirConverter : public Fortran::lower::AbstractConverter {
20282030
void handleLocalitySpecs(const IncrementLoopInfo &info) {
20292031
Fortran::semantics::SemanticsContext &semanticsContext =
20302032
bridge.getSemanticsContext();
2031-
for (const Fortran::semantics::Symbol *sym : info.localSymList)
2033+
2034+
Fortran::lower::omp::DataSharingProcessor dsp(
2035+
*this, semanticsContext, getEval(),
2036+
/*useDelayedPrivatization=*/true, localSymbols);
2037+
mlir::omp::PrivateClauseOps privateClauseOps;
2038+
auto doConcurrentLoopOp =
2039+
mlir::dyn_cast_if_present<fir::DoConcurrentLoopOp>(info.loopOp);
2040+
bool useDelayedPriv =
2041+
enableDelayedPrivatizationStaging && doConcurrentLoopOp;
2042+
2043+
for (const Fortran::semantics::Symbol *sym : info.localSymList) {
2044+
if (useDelayedPriv) {
2045+
dsp.doPrivatize(sym, &privateClauseOps);
2046+
continue;
2047+
}
2048+
20322049
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
2050+
}
2051+
20332052
for (const Fortran::semantics::Symbol *sym : info.localInitSymList) {
2053+
if (useDelayedPriv) {
2054+
dsp.doPrivatize(sym, &privateClauseOps);
2055+
continue;
2056+
}
2057+
20342058
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/true);
20352059
const auto *hostDetails =
20362060
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
@@ -2049,6 +2073,24 @@ class FirConverter : public Fortran::lower::AbstractConverter {
20492073
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
20502074
copySymbolBinding(hostDetails->symbol(), *sym);
20512075
}
2076+
2077+
if (useDelayedPriv) {
2078+
doConcurrentLoopOp.getPrivateVarsMutable().assign(
2079+
privateClauseOps.privateVars);
2080+
doConcurrentLoopOp.setPrivateSymsAttr(
2081+
builder->getArrayAttr(privateClauseOps.privateSyms));
2082+
2083+
for (auto [sym, privateVar] : llvm::zip_equal(
2084+
dsp.getAllSymbolsToPrivatize(), privateClauseOps.privateVars)) {
2085+
auto arg = doConcurrentLoopOp.getRegion().begin()->addArgument(
2086+
privateVar.getType(), doConcurrentLoopOp.getLoc());
2087+
bindSymbol(*sym, hlfir::translateToExtendedValue(
2088+
privateVar.getLoc(), *builder, hlfir::Entity{arg},
2089+
/*contiguousHint=*/true)
2090+
.first);
2091+
}
2092+
}
2093+
20522094
// Note that allocatable, types with ultimate components, and type
20532095
// requiring finalization are forbidden in LOCAL/LOCAL_INIT (F2023 C1130),
20542096
// so no clean-up needs to be generated for these entities.

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ DataSharingProcessor::DataSharingProcessor(
5353
});
5454
}
5555

56+
DataSharingProcessor::DataSharingProcessor(lower::AbstractConverter &converter,
57+
semantics::SemanticsContext &semaCtx,
58+
lower::pft::Evaluation &eval,
59+
bool useDelayedPrivatization,
60+
lower::SymMap &symTable)
61+
: DataSharingProcessor(converter, semaCtx, {}, eval,
62+
/*shouldCollectPreDeterminedSymols=*/false,
63+
useDelayedPrivatization, symTable) {}
64+
5665
void DataSharingProcessor::processStep1(
5766
mlir::omp::PrivateClauseOps *clauseOps) {
5867
collectSymbolsForPrivatization();
@@ -172,7 +181,8 @@ void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) {
172181

173182
void DataSharingProcessor::copyFirstPrivateSymbol(
174183
const semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *copyAssignIP) {
175-
if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate))
184+
if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
185+
sym->test(semantics::Symbol::Flag::LocalityLocalInit))
176186
converter.copyHostAssociateVar(*sym, copyAssignIP);
177187
}
178188

@@ -504,22 +514,29 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) {
504514
}
505515
}
506516

507-
void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
517+
void DataSharingProcessor::doPrivatize(const semantics::Symbol *symToPrivatize,
508518
mlir::omp::PrivateClauseOps *clauseOps) {
509519
if (!useDelayedPrivatization) {
510-
cloneSymbol(sym);
511-
copyFirstPrivateSymbol(sym);
520+
cloneSymbol(symToPrivatize);
521+
copyFirstPrivateSymbol(symToPrivatize);
512522
return;
513523
}
514524

515-
lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
525+
const semantics::Symbol *sym = symToPrivatize->HasLocalLocality()
526+
? &symToPrivatize->GetUltimate()
527+
: symToPrivatize;
528+
lower::SymbolBox hsb = symToPrivatize->HasLocalLocality()
529+
? converter.shallowLookupSymbol(*sym)
530+
: converter.lookupOneLevelUpSymbol(*sym);
516531
assert(hsb && "Host symbol box not found");
517532
hlfir::Entity entity{hsb.getAddr()};
518533
bool cannotHaveNonDefaultLowerBounds = !entity.mayHaveNonDefaultLowerBounds();
519534

520535
mlir::Location symLoc = hsb.getAddr().getLoc();
521536
std::string privatizerName = sym->name().ToString() + ".privatizer";
522-
bool isFirstPrivate = sym->test(semantics::Symbol::Flag::OmpFirstPrivate);
537+
bool isFirstPrivate =
538+
symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
539+
symToPrivatize->test(semantics::Symbol::Flag::LocalityLocalInit);
523540

524541
mlir::Value privVal = hsb.getAddr();
525542
mlir::Type allocType = privVal.getType();
@@ -613,27 +630,30 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
613630
&copyRegion, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc});
614631
firOpBuilder.setInsertionPointToEnd(copyEntryBlock);
615632

616-
auto addSymbol = [&](unsigned argIdx, bool force = false) {
633+
auto addSymbol = [&](unsigned argIdx, const semantics::Symbol *symToMap,
634+
bool force = false) {
617635
symExV.match(
618636
[&](const fir::MutableBoxValue &box) {
619637
symTable.addSymbol(
620-
*sym, fir::substBase(box, copyRegion.getArgument(argIdx)),
621-
force);
638+
*symToMap,
639+
fir::substBase(box, copyRegion.getArgument(argIdx)), force);
622640
},
623641
[&](const auto &box) {
624-
symTable.addSymbol(*sym, copyRegion.getArgument(argIdx), force);
642+
symTable.addSymbol(*symToMap, copyRegion.getArgument(argIdx),
643+
force);
625644
});
626645
};
627646

628-
addSymbol(0, true);
647+
addSymbol(0, sym, true);
629648
lower::SymMapScope innerScope(symTable);
630-
addSymbol(1);
649+
addSymbol(1, symToPrivatize);
631650

632651
auto ip = firOpBuilder.saveInsertionPoint();
633-
copyFirstPrivateSymbol(sym, &ip);
652+
copyFirstPrivateSymbol(symToPrivatize, &ip);
634653

635654
firOpBuilder.create<mlir::omp::YieldOp>(
636-
hsb.getAddr().getLoc(), symTable.shallowLookupSymbol(*sym).getAddr());
655+
hsb.getAddr().getLoc(),
656+
symTable.shallowLookupSymbol(*symToPrivatize).getAddr());
637657
}
638658

639659
return result;
@@ -645,6 +665,9 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
645665
}
646666

647667
symToPrivatizer[sym] = privatizerOp;
668+
669+
if (symToPrivatize->HasLocalLocality())
670+
allPrivatizedSymbols.insert(symToPrivatize);
648671
}
649672

650673
} // namespace omp

flang/lib/Lower/OpenMP/DataSharingProcessor.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ class DataSharingProcessor {
105105
void collectImplicitSymbols();
106106
void collectPreDeterminedSymbols();
107107
void privatize(mlir::omp::PrivateClauseOps *clauseOps);
108-
void doPrivatize(const semantics::Symbol *sym,
109-
mlir::omp::PrivateClauseOps *clauseOps);
110108
void copyLastPrivatize(mlir::Operation *op);
111109
void insertLastPrivateCompare(mlir::Operation *op);
112110
void cloneSymbol(const semantics::Symbol *sym);
@@ -125,6 +123,11 @@ class DataSharingProcessor {
125123
bool shouldCollectPreDeterminedSymbols,
126124
bool useDelayedPrivatization, lower::SymMap &symTable);
127125

126+
DataSharingProcessor(lower::AbstractConverter &converter,
127+
semantics::SemanticsContext &semaCtx,
128+
lower::pft::Evaluation &eval,
129+
bool useDelayedPrivatization, lower::SymMap &symTable);
130+
128131
// Privatisation is split into two steps.
129132
// Step1 performs cloning of all privatisation clauses and copying for
130133
// firstprivates. Step1 is performed at the place where process/processStep1
@@ -151,6 +154,9 @@ class DataSharingProcessor {
151154
? allPrivatizedSymbols.getArrayRef()
152155
: llvm::ArrayRef<const semantics::Symbol *>();
153156
}
157+
158+
void doPrivatize(const semantics::Symbol *sym,
159+
mlir::omp::PrivateClauseOps *clauseOps);
154160
};
155161

156162
} // namespace omp
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
! RUN: %flang_fc1 -emit-hlfir -mmlir --openmp-enable-delayed-privatization-staging=true -o - %s | FileCheck %s
2+
3+
subroutine do_concurrent_with_locality_specs
4+
implicit none
5+
integer :: i, local_var, local_init_var
6+
7+
do concurrent (i=1:10) local(local_var) local_init(local_init_var)
8+
if (i < 5) then
9+
local_var = 42
10+
else
11+
local_init_var = 84
12+
end if
13+
end do
14+
end subroutine
15+
16+
! CHECK-LABEL: omp.private {type = firstprivate} @_QFdo_concurrent_with_locality_specsElocal_init_var_firstprivate_i32 : i32 copy {
17+
! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>):
18+
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32>
19+
! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_1]] : i32, !fir.ref<i32>
20+
! CHECK: omp.yield(%[[VAL_1]] : !fir.ref<i32>)
21+
! CHECK: }
22+
! CHECK: omp.private {type = private} @_QFdo_concurrent_with_locality_specsElocal_var_private_i32 : i32
23+
24+
! CHECK-LABEL: func.func @_QPdo_concurrent_with_locality_specs() {
25+
! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
26+
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFdo_concurrent_with_locality_specsEi"}
27+
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFdo_concurrent_with_locality_specsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
28+
! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "local_init_var", uniq_name = "_QFdo_concurrent_with_locality_specsElocal_init_var"}
29+
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFdo_concurrent_with_locality_specsElocal_init_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
30+
! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "local_var", uniq_name = "_QFdo_concurrent_with_locality_specsElocal_var"}
31+
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFdo_concurrent_with_locality_specsElocal_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
32+
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
33+
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> index
34+
! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32
35+
! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
36+
! CHECK: %[[VAL_11:.*]] = arith.constant 1 : index
37+
! CHECK: fir.do_concurrent {
38+
! CHECK: %[[VAL_12:.*]] = fir.alloca i32 {bindc_name = "i"}
39+
! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFdo_concurrent_with_locality_specsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
40+
! CHECK: fir.do_concurrent.loop (%[[VAL_14:.*]]) = (%[[VAL_8]]) to (%[[VAL_10]]) step (%[[VAL_11]]) private(@_QFdo_concurrent_with_locality_specsElocal_var_private_i32 %[[VAL_6]]#0 -> %[[VAL_15:.*]], @_QFdo_concurrent_with_locality_specsElocal_init_var_firstprivate_i32 %[[VAL_4]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, !fir.ref<i32>) {
41+
! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_14]] : (index) -> i32
42+
! CHECK: fir.store %[[VAL_17]] to %[[VAL_13]]#0 : !fir.ref<i32>
43+
! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFdo_concurrent_with_locality_specsElocal_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
44+
! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFdo_concurrent_with_locality_specsElocal_init_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
45+
! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<i32>
46+
! CHECK: %[[VAL_21:.*]] = arith.constant 5 : i32
47+
! CHECK: %[[VAL_22:.*]] = arith.cmpi slt, %[[VAL_20]], %[[VAL_21]] : i32
48+
! CHECK: fir.if %[[VAL_22]] {
49+
! CHECK: %[[VAL_23:.*]] = arith.constant 42 : i32
50+
! CHECK: hlfir.assign %[[VAL_23]] to %[[VAL_18]]#0 : i32, !fir.ref<i32>
51+
! CHECK: } else {
52+
! CHECK: %[[VAL_24:.*]] = arith.constant 84 : i32
53+
! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_19]]#0 : i32, !fir.ref<i32>
54+
! CHECK: }
55+
! CHECK: }
56+
! CHECK: }
57+
! CHECK: return
58+
! CHECK: }

0 commit comments

Comments
 (0)