1212
1313#include " PrivateReductionUtils.h"
1414
15+ #include " flang/Optimizer/Builder/BoxValue.h"
16+ #include " flang/Optimizer/Builder/Character.h"
1517#include " flang/Optimizer/Builder/FIRBuilder.h"
1618#include " flang/Optimizer/Builder/HLFIRTools.h"
1719#include " flang/Optimizer/Builder/Todo.h"
20+ #include " flang/Optimizer/Dialect/FIROps.h"
21+ #include " flang/Optimizer/Dialect/FIRType.h"
1822#include " flang/Optimizer/HLFIR/HLFIROps.h"
1923#include " flang/Optimizer/Support/FatalError.h"
2024#include " mlir/Dialect/OpenMP/OpenMPDialect.h"
@@ -66,6 +70,21 @@ static void createCleanupRegion(fir::FirOpBuilder &builder, mlir::Location loc,
6670 return ;
6771 }
6872
73+ if (auto boxCharTy = mlir::dyn_cast<fir::BoxCharType>(argType)) {
74+ auto [addr, len] =
75+ fir::factory::CharacterExprHelper{builder, loc}.createUnboxChar (
76+ block->getArgument (0 ));
77+
78+ // convert addr to a heap type so it can be used with fir::FreeMemOp
79+ auto refTy = mlir::cast<fir::ReferenceType>(addr.getType ());
80+ auto heapTy = fir::HeapType::get (refTy.getEleTy ());
81+ addr = builder.createConvert (loc, heapTy, addr);
82+
83+ builder.create <fir::FreeMemOp>(loc, addr);
84+ builder.create <mlir::omp::YieldOp>(loc);
85+ return ;
86+ }
87+
6988 typeError ();
7089}
7190
@@ -129,14 +148,18 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
129148 // }
130149 // omp.yield %box_alloca
131150 moldArg = builder.loadIfRef (loc, moldArg);
151+ mlir::SmallVector<mlir::Value> lenParams;
152+ hlfir::genLengthParameters (loc, builder, hlfir::Entity{moldArg}, lenParams);
132153 auto handleNullAllocatable = [&](mlir::Value boxAlloca) -> fir::IfOp {
133154 mlir::Value addr = builder.create <fir::BoxAddrOp>(loc, moldArg);
134155 mlir::Value isNotAllocated = builder.genIsNullAddr (loc, addr);
135156 fir::IfOp ifOp = builder.create <fir::IfOp>(loc, isNotAllocated,
136157 /* withElseRegion=*/ true );
137158 builder.setInsertionPointToStart (&ifOp.getThenRegion ().front ());
138159 // just embox the null address and return
139- mlir::Value nullBox = builder.create <fir::EmboxOp>(loc, ty, addr);
160+ mlir::Value nullBox =
161+ builder.create <fir::EmboxOp>(loc, ty, addr, /* shape=*/ mlir::Value{},
162+ /* slice=*/ mlir::Value{}, lenParams);
140163 builder.create <fir::StoreOp>(loc, nullBox, boxAlloca);
141164 return ifOp;
142165 };
@@ -149,7 +172,8 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
149172 builder.setInsertionPointToEnd (initBlock);
150173 mlir::Value boxAlloca = allocatedPrivVarArg;
151174 mlir::Type innerTy = fir::unwrapRefType (boxTy.getEleTy ());
152- if (fir::isa_trivial (innerTy)) {
175+ bool isChar = fir::isa_char (innerTy);
176+ if (fir::isa_trivial (innerTy) || isChar) {
153177 // boxed non-sequence value e.g. !fir.box<!fir.heap<i32>>
154178 if (!isAllocatableOrPointer)
155179 TODO (loc,
@@ -158,10 +182,13 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
158182 fir::IfOp ifUnallocated = handleNullAllocatable (boxAlloca);
159183
160184 builder.setInsertionPointToStart (&ifUnallocated.getElseRegion ().front ());
161- mlir::Value valAlloc = builder.create <fir::AllocMemOp>(loc, innerTy);
185+ mlir::Value valAlloc = builder.createHeapTemporary (
186+ loc, innerTy, /* name=*/ {}, /* shape=*/ {}, lenParams);
162187 if (scalarInitValue)
163188 builder.createStoreWithConvert (loc, scalarInitValue, valAlloc);
164- mlir::Value box = builder.create <fir::EmboxOp>(loc, ty, valAlloc);
189+ mlir::Value box = builder.create <fir::EmboxOp>(
190+ loc, ty, valAlloc, /* shape=*/ mlir::Value{}, /* slice=*/ mlir::Value{},
191+ lenParams);
165192 builder.create <fir::StoreOp>(loc, box, boxAlloca);
166193
167194 createCleanupRegion (builder, loc, argType, cleanupRegion);
@@ -170,7 +197,7 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
170197 return ;
171198 }
172199 innerTy = fir::extractSequenceType (boxTy);
173- if (!mlir::isa<fir::SequenceType>(innerTy))
200+ if (!innerTy || ! mlir::isa<fir::SequenceType>(innerTy))
174201 TODO (loc, " Unsupported boxed type for reduction/privatization" );
175202
176203 fir::IfOp ifUnallocated{nullptr };
@@ -230,6 +257,31 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
230257 return ;
231258 }
232259
260+ if (auto boxCharTy = mlir::dyn_cast<fir::BoxCharType>(argType)) {
261+ mlir::Type eleTy = boxCharTy.getEleTy ();
262+ builder.setInsertionPointToStart (initBlock);
263+ fir::factory::CharacterExprHelper charExprHelper{builder, loc};
264+ auto [addr, len] = charExprHelper.createUnboxChar (moldArg);
265+
266+ // Using heap temporary so that
267+ // 1) It is safe to use privatization inside of big loops.
268+ // 2) The lifetime can outlive the current stack frame for delayed task
269+ // execution.
270+ // We can't always allocate a boxchar implicitly as the type of the
271+ // omp.private because the allocation potentially needs the length
272+ // parameters fetched above.
273+ // TODO: this deviates from the intended design for delayed task execution.
274+ mlir::Value privateAddr = builder.createHeapTemporary (
275+ loc, eleTy, /* name=*/ {}, /* shape=*/ {}, /* lenParams=*/ len);
276+ mlir::Value boxChar = charExprHelper.createEmboxChar (privateAddr, len);
277+
278+ createCleanupRegion (builder, loc, argType, cleanupRegion);
279+
280+ builder.setInsertionPointToEnd (initBlock);
281+ yield (boxChar);
282+ return ;
283+ }
284+
233285 TODO (loc,
234286 " creating reduction/privatization init region for unsupported type" );
235287 return ;
0 commit comments