1717#include " flang/Lower/OpenMP/Utils.h"
1818#include " flang/Lower/PFTBuilder.h"
1919#include " flang/Lower/SymbolMap.h"
20- #include " flang/Optimizer/Builder/BoxValue.h"
2120#include " flang/Optimizer/Builder/HLFIRTools.h"
2221#include " flang/Optimizer/Builder/Todo.h"
23- #include " flang/Optimizer/HLFIR/HLFIRDialect.h"
2422#include " flang/Optimizer/HLFIR/HLFIROps.h"
25- #include " flang/Semantics/attr.h"
2623#include " flang/Semantics/tools.h"
2724
2825namespace Fortran {
@@ -94,65 +91,35 @@ void DataSharingProcessor::insertDeallocs() {
9491 converter.createHostAssociateVarCloneDealloc (*sym);
9592 continue ;
9693 }
97- // For delayed privatization deallocs are created by
98- // populateByRefInitAndCleanupRegions
94+
95+ lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol (*sym);
96+ assert (hsb && " Host symbol box not found" );
97+ mlir::Type symType = hsb.getAddr ().getType ();
98+ mlir::Location symLoc = hsb.getAddr ().getLoc ();
99+ fir::ExtendedValue symExV = converter.getSymbolExtendedValue (*sym);
100+ mlir::omp::PrivateClauseOp privatizer = symToPrivatizer.at (sym);
101+
102+ lower::SymMapScope scope (symTable);
103+ mlir::OpBuilder::InsertionGuard guard (firOpBuilder);
104+
105+ mlir::Region &deallocRegion = privatizer.getDeallocRegion ();
106+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
107+ mlir::Block *deallocEntryBlock = firOpBuilder.createBlock (
108+ &deallocRegion, /* insertPt=*/ {}, symType, symLoc);
109+
110+ firOpBuilder.setInsertionPointToEnd (deallocEntryBlock);
111+ symTable.addSymbol (*sym,
112+ fir::substBase (symExV, deallocRegion.getArgument (0 )));
113+
114+ converter.createHostAssociateVarCloneDealloc (*sym);
115+ firOpBuilder.create <mlir::omp::YieldOp>(hsb.getAddr ().getLoc ());
99116 }
100117}
101118
102119void DataSharingProcessor::cloneSymbol (const semantics::Symbol *sym) {
103120 bool isFirstPrivate = sym->test (semantics::Symbol::Flag::OmpFirstPrivate);
104-
105- // If we are doing eager-privatization on a symbol created using delayed
106- // privatization there could be incompatible types here e.g.
107- // fir.ref<fir.box<fir.array<>>>
108- bool success = [&]() -> bool {
109- const auto *details =
110- sym->detailsIf <Fortran::semantics::HostAssocDetails>();
111- assert (details && " No host-association found" );
112- const Fortran::semantics::Symbol &hsym = details->symbol ();
113- mlir::Value addr = converter.getSymbolAddress (hsym);
114-
115- if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(addr.getType ())) {
116- if (auto boxTy = mlir::dyn_cast<fir::BoxType>(refTy.getElementType ())) {
117- if (auto arrayTy =
118- mlir::dyn_cast<fir::SequenceType>(boxTy.getElementType ())) {
119- // FirConverter/fir::ExtendedValue considers all references to boxes
120- // as mutable boxes. Outside of OpenMP it doesn't make sense to have a
121- // mutable box of an array. Work around this here by loading the
122- // reference so it is a normal boxed array.
123- fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
124- mlir::Location loc = converter.genLocation (hsym.name ());
125- fir::ExtendedValue hexv = converter.getSymbolExtendedValue (hsym);
126-
127- llvm::SmallVector<mlir::Value> extents =
128- fir::factory::getExtents (loc, builder, hexv);
129-
130- // TODO: uniqName, name
131- mlir::Value allocVal =
132- builder.allocateLocal (loc, arrayTy, /* uniqName=*/ " " ,
133- /* name=*/ " " , extents, /* typeParams=*/ {},
134- sym->GetUltimate ().attrs ().test (
135- Fortran::semantics::Attr::TARGET));
136- mlir::Value shape = builder.genShape (loc, extents);
137- mlir::Value box = builder.createBox (loc, boxTy, allocVal, shape,
138- nullptr , {}, nullptr );
139-
140- // This can't be a CharArrayBoxValue because otherwise
141- // boxTy.getElementType() would be a character type.
142- // Assume the array element type isn't polymorphic because we are
143- // privatizing.
144- fir::ExtendedValue newExv = fir::ArrayBoxValue{box, extents};
145-
146- converter.bindSymbol (*sym, newExv);
147- return true ;
148- }
149- }
150- }
151-
152- // Normal case:
153- return converter.createHostAssociateVarClone (
154- *sym, /* skipDefaultInit=*/ isFirstPrivate);
155- }();
121+ bool success = converter.createHostAssociateVarClone (
122+ *sym, /* skipDefaultInit=*/ isFirstPrivate);
156123 (void )success;
157124 assert (success && " Privatization failed due to existing binding" );
158125
@@ -171,7 +138,7 @@ void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) {
171138
172139 if (needInitClone ()) {
173140 Fortran::lower::initializeCloneAtRuntime (converter, *sym, symTable);
174- mightHaveReadHostSym = true ;
141+ callsInitClone = true ;
175142 }
176143}
177144
@@ -223,8 +190,7 @@ bool DataSharingProcessor::needBarrier() {
223190 // Emit implicit barrier for linear clause. Maybe on somewhere else.
224191 for (const semantics::Symbol *sym : allPrivatizedSymbols) {
225192 if (sym->test (semantics::Symbol::Flag::OmpLastPrivate) &&
226- (sym->test (semantics::Symbol::Flag::OmpFirstPrivate) ||
227- mightHaveReadHostSym))
193+ (sym->test (semantics::Symbol::Flag::OmpFirstPrivate) || callsInitClone))
228194 return true ;
229195 }
230196 return false ;
@@ -509,47 +475,15 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
509475 lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol (*sym);
510476 assert (hsb && " Host symbol box not found" );
511477
478+ mlir::Type symType = hsb.getAddr ().getType ();
512479 mlir::Location symLoc = hsb.getAddr ().getLoc ();
513480 std::string privatizerName = sym->name ().ToString () + " .privatizer" ;
514481 bool isFirstPrivate = sym->test (semantics::Symbol::Flag::OmpFirstPrivate);
515482
516- mlir::Value privVal = hsb.getAddr ();
517- mlir::Type allocType = privVal.getType ();
518- if (!mlir::isa<fir::PointerType>(privVal.getType ()))
519- allocType = fir::unwrapRefType (privVal.getType ());
520-
521- if (auto poly = mlir::dyn_cast<fir::ClassType>(allocType)) {
522- if (!mlir::isa<fir::PointerType>(poly.getEleTy ()) && isFirstPrivate)
523- TODO (symLoc, " create polymorphic host associated copy" );
524- }
525-
526- // fir.array<> cannot be converted to any single llvm type and fir helpers
527- // are not available in openmp to llvmir translation so we cannot generate
528- // an alloca for a fir.array type there. Get around this by boxing all
529- // arrays.
530- if (mlir::isa<fir::SequenceType>(allocType)) {
531- hlfir::Entity entity{hsb.getAddr ()};
532- entity = genVariableBox (symLoc, firOpBuilder, entity);
533- privVal = entity.getBase ();
534- allocType = privVal.getType ();
535- }
536-
537- if (mlir::isa<fir::BaseBoxType>(privVal.getType ())) {
538- // Boxes should be passed by reference into nested regions:
539- auto oldIP = firOpBuilder.saveInsertionPoint ();
540- firOpBuilder.setInsertionPointToStart (firOpBuilder.getAllocaBlock ());
541- auto alloca = firOpBuilder.create <fir::AllocaOp>(symLoc, privVal.getType ());
542- firOpBuilder.restoreInsertionPoint (oldIP);
543- firOpBuilder.create <fir::StoreOp>(symLoc, privVal, alloca);
544- privVal = alloca;
545- }
546-
547- mlir::Type argType = privVal.getType ();
548-
549483 mlir::omp::PrivateClauseOp privatizerOp = [&]() {
550484 auto moduleOp = firOpBuilder.getModule ();
551485 auto uniquePrivatizerName = fir::getTypeAsString (
552- allocType , converter.getKindMap (),
486+ symType , converter.getKindMap (),
553487 converter.mangleName (*sym) +
554488 (isFirstPrivate ? " _firstprivate" : " _private" ));
555489
@@ -561,40 +495,44 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
561495 mlir::OpBuilder::InsertionGuard guard (firOpBuilder);
562496 firOpBuilder.setInsertionPointToStart (moduleOp.getBody ());
563497 auto result = firOpBuilder.create <mlir::omp::PrivateClauseOp>(
564- symLoc, uniquePrivatizerName, allocType ,
498+ symLoc, uniquePrivatizerName, symType ,
565499 isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate
566500 : mlir::omp::DataSharingClauseType::Private);
567501 fir::ExtendedValue symExV = converter.getSymbolExtendedValue (*sym);
568502 lower::SymMapScope outerScope (symTable);
569503
570- // Populate the `init` region.
571- // We need to initialize in the following cases:
572- // 1. The allocation was for a derived type which requires initialization
573- // (this can be skipped if it will be initialized anyway by the copy
574- // region, unless the derived type has allocatable components)
575- // 2. The allocation was for any kind of box
576- // 3. The allocation was for a boxed character
577- const bool needsInitialization =
578- (Fortran::lower::hasDefaultInitialization (sym->GetUltimate ()) &&
579- (!isFirstPrivate || hlfir::mayHaveAllocatableComponent (allocType))) ||
580- mlir::isa<fir::BaseBoxType>(allocType) ||
581- mlir::isa<fir::BoxCharType>(allocType);
582- if (needsInitialization) {
583- mlir::Region &initRegion = result.getInitRegion ();
584- mlir::Block *initBlock = firOpBuilder.createBlock (
585- &initRegion, /* insertPt=*/ {}, {argType, argType}, {symLoc, symLoc});
586-
587- populateByRefInitAndCleanupRegions (
588- converter, symLoc, argType, /* scalarInitValue=*/ nullptr , initBlock,
589- result.getInitPrivateArg (), result.getInitMoldArg (),
590- result.getDeallocRegion (),
591- isFirstPrivate ? DeclOperationKind::FirstPrivate
592- : DeclOperationKind::Private,
593- sym);
594- // TODO: currently there are false positives from dead uses of the mold
595- // arg
596- if (!result.getInitMoldArg ().getUses ().empty ())
597- mightHaveReadHostSym = true ;
504+ // Populate the `alloc` region.
505+ {
506+ mlir::Region &allocRegion = result.getAllocRegion ();
507+ mlir::Block *allocEntryBlock = firOpBuilder.createBlock (
508+ &allocRegion, /* insertPt=*/ {}, symType, symLoc);
509+
510+ firOpBuilder.setInsertionPointToEnd (allocEntryBlock);
511+
512+ fir::ExtendedValue localExV =
513+ hlfir::translateToExtendedValue (
514+ symLoc, firOpBuilder, hlfir::Entity{allocRegion.getArgument (0 )},
515+ /* contiguousHint=*/
516+ evaluate::IsSimplyContiguous (*sym, converter.getFoldingContext ()))
517+ .first ;
518+
519+ symTable.addSymbol (*sym, localExV);
520+ lower::SymMapScope innerScope (symTable);
521+ cloneSymbol (sym);
522+ mlir::Value cloneAddr = symTable.shallowLookupSymbol (*sym).getAddr ();
523+ mlir::Type cloneType = cloneAddr.getType ();
524+
525+ // A `convert` op is required for variables that are storage associated
526+ // via `equivalence`. The problem is that these variables are declared as
527+ // `fir.ptr`s while their privatized storage is declared as `fir.ref`,
528+ // therefore we convert to proper symbol type.
529+ mlir::Value yieldedValue =
530+ (symType == cloneType) ? cloneAddr
531+ : firOpBuilder.createConvert (
532+ cloneAddr.getLoc (), symType, cloneAddr);
533+
534+ firOpBuilder.create <mlir::omp::YieldOp>(hsb.getAddr ().getLoc (),
535+ yieldedValue);
598536 }
599537
600538 // Populate the `copy` region if this is a `firstprivate`.
@@ -603,7 +541,7 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
603541 // First block argument corresponding to the original/host value while
604542 // second block argument corresponding to the privatized value.
605543 mlir::Block *copyEntryBlock = firOpBuilder.createBlock (
606- ©Region, /* insertPt=*/ {}, {argType, argType }, {symLoc, symLoc});
544+ ©Region, /* insertPt=*/ {}, {symType, symType }, {symLoc, symLoc});
607545 firOpBuilder.setInsertionPointToEnd (copyEntryBlock);
608546
609547 auto addSymbol = [&](unsigned argIdx, bool force = false ) {
@@ -634,7 +572,7 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
634572
635573 if (clauseOps) {
636574 clauseOps->privateSyms .push_back (mlir::SymbolRefAttr::get (privatizerOp));
637- clauseOps->privateVars .push_back (privVal );
575+ clauseOps->privateVars .push_back (hsb. getAddr () );
638576 }
639577
640578 symToPrivatizer[sym] = privatizerOp;
0 commit comments