1313#include " flang/Optimizer/Builder/Character.h"
1414#include " flang/Optimizer/Builder/FIRBuilder.h"
1515#include " flang/Optimizer/Builder/Factory.h"
16+ #include " flang/Optimizer/Builder/Runtime/Derived.h"
1617#include " flang/Optimizer/Dialect/FIRDialect.h"
1718#include " flang/Optimizer/Dialect/FIROpsSupport.h"
1819#include " flang/Optimizer/Support/FIRContext.h"
@@ -999,6 +1000,50 @@ findNonconstantExtents(mlir::Type memrefTy,
9991000 return nce;
10001001}
10011002
1003+ // / Allocate temporary storage for an ArrayLoadOp \load and initialize any
1004+ // / allocatable direct components of the array elements with an unallocated
1005+ // / status. Returns the temporary address as well as a callback to generate the
1006+ // / temporary clean-up once it has been used. The clean-up will take care of
1007+ // / deallocating all the element allocatable components that may have been
1008+ // / allocated while using the temporary.
1009+ static std::pair<mlir::Value,
1010+ std::function<void (mlir::PatternRewriter &rewriter)>>
1011+ allocateArrayTemp (mlir::Location loc, mlir::PatternRewriter &rewriter,
1012+ ArrayLoadOp load, llvm::ArrayRef<mlir::Value> extents,
1013+ mlir::Value shape) {
1014+ mlir::Type baseType = load.memref ().getType ();
1015+ llvm::SmallVector<mlir::Value> nonconstantExtents =
1016+ findNonconstantExtents (baseType, extents);
1017+ llvm::SmallVector<mlir::Value> typeParams =
1018+ genArrayLoadTypeParameters (loc, rewriter, load);
1019+ mlir::Value allocmem = rewriter.create <AllocMemOp>(
1020+ loc, dyn_cast_ptrOrBoxEleTy (baseType), typeParams, nonconstantExtents);
1021+ mlir::Type eleType =
1022+ fir::unwrapSequenceType (fir::unwrapPassByRefType (baseType));
1023+ if (fir::isRecordWithAllocatableMember (eleType)) {
1024+ // The allocatable component descriptors need to be set to a clean
1025+ // deallocated status before anything is done with them.
1026+ mlir::Value box = rewriter.create <fir::EmboxOp>(
1027+ loc, fir::BoxType::get (baseType), allocmem, shape,
1028+ /* slice=*/ mlir::Value{}, typeParams);
1029+ auto module = load->getParentOfType <mlir::ModuleOp>();
1030+ FirOpBuilder builder (rewriter, getKindMapping (module ));
1031+ runtime::genDerivedTypeInitialize (builder, loc, box);
1032+ // Any allocatable component that may have been allocated must be
1033+ // deallocated during the clean-up.
1034+ auto cleanup = [=](mlir::PatternRewriter &r) {
1035+ FirOpBuilder builder (r, getKindMapping (module ));
1036+ runtime::genDerivedTypeDestroy (builder, loc, box);
1037+ r.create <FreeMemOp>(loc, allocmem);
1038+ };
1039+ return {allocmem, cleanup};
1040+ }
1041+ auto cleanup = [=](mlir::PatternRewriter &r) {
1042+ r.create <FreeMemOp>(loc, allocmem);
1043+ };
1044+ return {allocmem, cleanup};
1045+ }
1046+
10021047namespace {
10031048// / Conversion of fir.array_update and fir.array_modify Ops.
10041049// / If there is a conflict for the update, then we need to perform a
@@ -1030,11 +1075,8 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern<ArrayOp> {
10301075 bool copyUsingSlice = false ;
10311076 auto shapeOp = getOrReadExtentsAndShapeOp (loc, rewriter, load, extents,
10321077 copyUsingSlice);
1033- llvm::SmallVector<mlir::Value> nonconstantExtents =
1034- findNonconstantExtents (load.memref ().getType (), extents);
1035- auto allocmem = rewriter.create <AllocMemOp>(
1036- loc, dyn_cast_ptrOrBoxEleTy (load.memref ().getType ()),
1037- genArrayLoadTypeParameters (loc, rewriter, load), nonconstantExtents);
1078+ auto [allocmem, genTempCleanUp] =
1079+ allocateArrayTemp (loc, rewriter, load, extents, shapeOp);
10381080 genArrayCopy</* copyIn=*/ true >(load.getLoc (), rewriter, allocmem,
10391081 load.memref (), shapeOp, load.slice (), load);
10401082 // Generate the reference for the access.
@@ -1050,7 +1092,7 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern<ArrayOp> {
10501092 // Copy out.
10511093 genArrayCopy</* copyIn=*/ false >(store.getLoc (), rewriter, store.memref (),
10521094 allocmem, shapeOp, store.slice (), load);
1053- rewriter. create <FreeMemOp>(loc, allocmem );
1095+ genTempCleanUp (rewriter );
10541096 return coor;
10551097 }
10561098
@@ -1080,11 +1122,9 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern<ArrayOp> {
10801122 bool copyUsingSlice = false ;
10811123 auto shapeOp = getOrReadExtentsAndShapeOp (loc, rewriter, load, extents,
10821124 copyUsingSlice);
1083- llvm::SmallVector<mlir::Value> nonconstantExtents =
1084- findNonconstantExtents (load.memref ().getType (), extents);
1085- auto allocmem = rewriter.create <AllocMemOp>(
1086- loc, dyn_cast_ptrOrBoxEleTy (load.memref ().getType ()),
1087- genArrayLoadTypeParameters (loc, rewriter, load), nonconstantExtents);
1125+ auto [allocmem, genTempCleanUp] =
1126+ allocateArrayTemp (loc, rewriter, load, extents, shapeOp);
1127+
10881128 genArrayCopy</* copyIn=*/ true >(load.getLoc (), rewriter, allocmem,
10891129 load.memref (), shapeOp, load.slice (), load);
10901130 rewriter.setInsertionPoint (op);
@@ -1100,7 +1140,7 @@ class ArrayUpdateConversionBase : public mlir::OpRewritePattern<ArrayOp> {
11001140 // Copy out.
11011141 genArrayCopy</* copyIn=*/ false >(store.getLoc (), rewriter, store.memref (),
11021142 allocmem, shapeOp, store.slice (), load);
1103- rewriter. create <FreeMemOp>(loc, allocmem );
1143+ genTempCleanUp (rewriter );
11041144 return {coor, load.getResult ()};
11051145 }
11061146 // Otherwise, when there is no conflict (a possible loop-carried
0 commit comments