Skip to content

Commit 0832f1a

Browse files
authored
[flang][OpenACC] generate Destroy region to free memory of private and firstprivate if needed (#162702)
This patch extends the MappableTypeInterface to: - allow genPrivateInit to indicate that a Destroy region will be needed. - add genPrivateDestroy to generate the destruction code - Implement both interfaces in FIR - Update OpenACC lowering to generate the Destroy region when needed using those interfaces.
1 parent 145f21c commit 0832f1a

File tree

8 files changed

+201
-11
lines changed

8 files changed

+201
-11
lines changed

flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ struct OpenACCMappableModel
5757
mlir::Location loc,
5858
mlir::TypedValue<mlir::acc::MappableType> var,
5959
llvm::StringRef varName,
60-
mlir::ValueRange extents,
61-
mlir::Value initVal) const;
60+
mlir::ValueRange extents, mlir::Value initVal,
61+
bool &needsDestroy) const;
62+
63+
bool generatePrivateDestroy(mlir::Type type, mlir::OpBuilder &builder,
64+
mlir::Location loc, mlir::Value privatized) const;
6265
};
6366

6467
} // namespace fir::acc

flang/include/flang/Optimizer/Support/Utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ std::optional<llvm::ArrayRef<int64_t>> getComponentLowerBoundsIfNonDefault(
200200
fir::RecordType recordType, llvm::StringRef component,
201201
mlir::ModuleOp module, const mlir::SymbolTable *symbolTable = nullptr);
202202

203+
/// Indicate if a derived type has final routine. Returns std::nullopt if that
204+
/// information is not in the IR;
205+
std::optional<bool>
206+
isRecordWithFinalRoutine(fir::RecordType recordType, mlir::ModuleOp module,
207+
const mlir::SymbolTable *symbolTable = nullptr);
208+
203209
/// Generate a LLVM constant value of type `ity`, using the provided offset.
204210
mlir::LLVM::ConstantOp
205211
genConstantIndex(mlir::Location loc, mlir::Type ity,

flang/lib/Lower/OpenACC.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,15 +978,40 @@ static RecipeOp genRecipeOp(
978978
auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
979979
assert(mappableTy &&
980980
"Expected that all variable types are considered mappable");
981+
bool needsDestroy = false;
981982
auto retVal = mappableTy.generatePrivateInit(
982983
builder, loc,
983984
mlir::cast<mlir::TypedValue<mlir::acc::MappableType>>(
984985
initBlock->getArgument(0)),
985986
initName,
986987
initBlock->getArguments().take_back(initBlock->getArguments().size() - 1),
987-
initValue);
988+
initValue, needsDestroy);
988989
mlir::acc::YieldOp::create(builder, loc,
989990
retVal ? retVal : initBlock->getArgument(0));
991+
// Create destroy region and generate destruction if requested.
992+
if (needsDestroy) {
993+
llvm::SmallVector<mlir::Type> destroyArgsTy;
994+
llvm::SmallVector<mlir::Location> destroyArgsLoc;
995+
// original and privatized/reduction value
996+
destroyArgsTy.push_back(ty);
997+
destroyArgsTy.push_back(ty);
998+
destroyArgsLoc.push_back(loc);
999+
destroyArgsLoc.push_back(loc);
1000+
// Append bounds arguments (if any) in the same order as init region
1001+
if (argsTy.size() > 1) {
1002+
destroyArgsTy.append(argsTy.begin() + 1, argsTy.end());
1003+
destroyArgsLoc.insert(destroyArgsLoc.end(), argsTy.size() - 1, loc);
1004+
}
1005+
1006+
builder.createBlock(&recipe.getDestroyRegion(),
1007+
recipe.getDestroyRegion().end(), destroyArgsTy,
1008+
destroyArgsLoc);
1009+
builder.setInsertionPointToEnd(&recipe.getDestroyRegion().back());
1010+
// Call interface on the privatized/reduction value (2nd argument).
1011+
(void)mappableTy.generatePrivateDestroy(
1012+
builder, loc, recipe.getDestroyRegion().front().getArgument(1));
1013+
mlir::acc::TerminatorOp::create(builder, loc);
1014+
}
9901015
return recipe;
9911016
}
9921017

flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "flang/Optimizer/Dialect/FIRType.h"
2222
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
2323
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
24+
#include "flang/Optimizer/Support/Utils.h"
2425
#include "mlir/Dialect/Arith/IR/Arith.h"
2526
#include "mlir/Dialect/OpenACC/OpenACC.h"
2627
#include "mlir/IR/BuiltinOps.h"
@@ -548,14 +549,27 @@ template <typename Ty>
548549
mlir::Value OpenACCMappableModel<Ty>::generatePrivateInit(
549550
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
550551
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
551-
mlir::ValueRange extents, mlir::Value initVal) const {
552+
mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const {
553+
needsDestroy = false;
552554
mlir::Value retVal;
553555
mlir::Type unwrappedTy = fir::unwrapRefType(type);
554556
mlir::ModuleOp mod = builder.getInsertionBlock()
555557
->getParent()
556558
->getParentOfType<mlir::ModuleOp>();
557-
fir::FirOpBuilder firBuilder(builder, mod);
558559

560+
if (auto recType = llvm::dyn_cast<fir::RecordType>(
561+
fir::getFortranElementType(unwrappedTy))) {
562+
// Need to make deep copies of allocatable components.
563+
if (fir::isRecordWithAllocatableMember(recType))
564+
TODO(loc,
565+
"OpenACC: privatizing derived type with allocatable components");
566+
// Need to decide if user assignment/final routine should be called.
567+
if (fir::isRecordWithFinalRoutine(recType, mod).value_or(false))
568+
TODO(loc, "OpenACC: privatizing derived type with user assignment or "
569+
"final routine ");
570+
}
571+
572+
fir::FirOpBuilder firBuilder(builder, mod);
559573
auto getDeclareOpForType = [&](mlir::Type ty) -> hlfir::DeclareOp {
560574
auto alloca = fir::AllocaOp::create(firBuilder, loc, ty);
561575
return hlfir::DeclareOp::create(firBuilder, loc, alloca, varName);
@@ -615,9 +629,11 @@ mlir::Value OpenACCMappableModel<Ty>::generatePrivateInit(
615629
mlir::Value firClass =
616630
fir::EmboxOp::create(builder, loc, boxTy, allocatedScalar);
617631
fir::StoreOp::create(builder, loc, firClass, retVal);
632+
needsDestroy = true;
618633
} else if (mlir::isa<fir::SequenceType>(innerTy)) {
619634
hlfir::Entity source = hlfir::Entity{var};
620-
auto [temp, cleanup] = hlfir::createTempFromMold(loc, firBuilder, source);
635+
auto [temp, cleanupFlag] =
636+
hlfir::createTempFromMold(loc, firBuilder, source);
621637
if (fir::isa_ref_type(type)) {
622638
// When the temp is created - it is not a reference - thus we can
623639
// end up with a type inconsistency. Therefore ensure storage is created
@@ -636,6 +652,9 @@ mlir::Value OpenACCMappableModel<Ty>::generatePrivateInit(
636652
} else {
637653
retVal = temp;
638654
}
655+
// If heap was allocated, a destroy is required later.
656+
if (cleanupFlag)
657+
needsDestroy = true;
639658
} else {
640659
TODO(loc, "Unsupported boxed type for OpenACC private-like recipe");
641660
}
@@ -667,23 +686,61 @@ template mlir::Value
667686
OpenACCMappableModel<fir::BaseBoxType>::generatePrivateInit(
668687
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
669688
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
670-
mlir::ValueRange extents, mlir::Value initVal) const;
689+
mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
671690

672691
template mlir::Value
673692
OpenACCMappableModel<fir::ReferenceType>::generatePrivateInit(
674693
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
675694
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
676-
mlir::ValueRange extents, mlir::Value initVal) const;
695+
mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
677696

678697
template mlir::Value OpenACCMappableModel<fir::HeapType>::generatePrivateInit(
679698
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
680699
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
681-
mlir::ValueRange extents, mlir::Value initVal) const;
700+
mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
682701

683702
template mlir::Value
684703
OpenACCMappableModel<fir::PointerType>::generatePrivateInit(
685704
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
686705
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
687-
mlir::ValueRange extents, mlir::Value initVal) const;
706+
mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
707+
708+
template <typename Ty>
709+
bool OpenACCMappableModel<Ty>::generatePrivateDestroy(
710+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
711+
mlir::Value privatized) const {
712+
mlir::Type unwrappedTy = fir::unwrapRefType(type);
713+
// For boxed scalars allocated with AllocMem during init, free the heap.
714+
if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(unwrappedTy)) {
715+
mlir::Value boxVal = privatized;
716+
if (fir::isa_ref_type(boxVal.getType()))
717+
boxVal = fir::LoadOp::create(builder, loc, boxVal);
718+
mlir::Value addr = fir::BoxAddrOp::create(builder, loc, boxVal);
719+
// FreeMem only accepts fir.heap and this may not be represented in the box
720+
// type if the privatized entity is not an allocatable.
721+
mlir::Type heapType =
722+
fir::HeapType::get(fir::unwrapRefType(addr.getType()));
723+
if (heapType != addr.getType())
724+
addr = fir::ConvertOp::create(builder, loc, heapType, addr);
725+
fir::FreeMemOp::create(builder, loc, addr);
726+
return true;
727+
}
728+
729+
// Nothing to do for other categories by default, they are stack allocated.
730+
return true;
731+
}
732+
733+
template bool OpenACCMappableModel<fir::BaseBoxType>::generatePrivateDestroy(
734+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
735+
mlir::Value privatized) const;
736+
template bool OpenACCMappableModel<fir::ReferenceType>::generatePrivateDestroy(
737+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
738+
mlir::Value privatized) const;
739+
template bool OpenACCMappableModel<fir::HeapType>::generatePrivateDestroy(
740+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
741+
mlir::Value privatized) const;
742+
template bool OpenACCMappableModel<fir::PointerType>::generatePrivateDestroy(
743+
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
744+
mlir::Value privatized) const;
688745

689746
} // namespace fir::acc

flang/lib/Optimizer/Support/Utils.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ std::optional<llvm::ArrayRef<int64_t>> fir::getComponentLowerBoundsIfNonDefault(
5151
return std::nullopt;
5252
}
5353

54+
std::optional<bool>
55+
fir::isRecordWithFinalRoutine(fir::RecordType recordType, mlir::ModuleOp module,
56+
const mlir::SymbolTable *symbolTable) {
57+
fir::TypeInfoOp typeInfo =
58+
fir::lookupTypeInfoOp(recordType, module, symbolTable);
59+
if (!typeInfo)
60+
return std::nullopt;
61+
return !typeInfo.getNoFinal();
62+
}
63+
5464
mlir::LLVM::ConstantOp
5565
fir::genConstantIndex(mlir::Location loc, mlir::Type ity,
5666
mlir::ConversionPatternRewriter &rewriter,

flang/test/Lower/OpenACC/acc-firstprivate-derived-allocatable-component.f90

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s
55
! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR-CHECK
66

7+
! TODO: This test hits a fatal TODO. Deal with allocatable component
8+
! destructions. For arrays, allocatable component allocation may also be
9+
! missing.
10+
! XFAIL: *
11+
712
module m_firstprivate_derived_alloc_comp
813
type point
914
real, allocatable :: x(:)

flang/test/Lower/OpenACC/acc-private.f90

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626
! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> !fir.box<!fir.array<?x?x2xi32>>
2727
! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.box<!fir.array<?x?x2xi32>>, !fir.box<!fir.array<?x?x2xi32>>
2828
! CHECK: acc.terminator
29+
! CHECK: } destroy {
30+
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?x?x2xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?x?x2xi32>>):
31+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?x?x2xi32>>) -> !fir.ref<!fir.array<?x?x2xi32>>
32+
! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : (!fir.ref<!fir.array<?x?x2xi32>>) -> !fir.heap<!fir.array<?x?x2xi32>>
33+
! CHECK: fir.freemem %[[CAST]] : !fir.heap<!fir.array<?x?x2xi32>>
34+
! CHECK: acc.terminator
2935
! CHECK: }
3036

3137
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb4.ub9_box_Uxi32 : !fir.box<!fir.array<?xi32>> init {
@@ -47,6 +53,12 @@
4753
! CHECK: %[[RIGHT:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
4854
! CHECK: hlfir.assign %[[LEFT]] to %[[RIGHT]] : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>
4955
! CHECK: acc.terminator
56+
! CHECK: } destroy {
57+
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>):
58+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
59+
! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>>
60+
! CHECK: fir.freemem %[[CAST]] : !fir.heap<!fir.array<?xi32>>
61+
! CHECK: acc.terminator
5062
! CHECK: }
5163

5264
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_box_Uxi32 : !fir.box<!fir.array<?xi32>> init {
@@ -64,6 +76,12 @@
6476
! CHECK: %[[DES_V2:.*]] = hlfir.designate %[[ARG1]] shape %[[SHAPE]] : (!fir.box<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
6577
! CHECK: hlfir.assign %[[DES_V1]] to %[[DES_V2]] : !fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>
6678
! CHECK: acc.terminator
79+
! CHECK: } destroy {
80+
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>):
81+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
82+
! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>>
83+
! CHECK: fir.freemem %[[CAST]] : !fir.heap<!fir.array<?xi32>>
84+
! CHECK: acc.terminator
6785
! CHECK: }
6886

6987
! CHECK-LABEL: acc.private.recipe @privatization_box_UxUx2xi32 : !fir.box<!fir.array<?x?x2xi32>> init {
@@ -74,6 +92,12 @@
7492
! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?x?x2xi32>, %[[DIM0]]#1, %[[DIM1]]#1 {bindc_name = ".tmp", uniq_name = ""}
7593
! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.heap<!fir.array<?x?x2xi32>>)
7694
! CHECK: acc.yield %[[DECL]]#0 : !fir.box<!fir.array<?x?x2xi32>>
95+
! CHECK: } destroy {
96+
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?x?x2xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?x?x2xi32>>):
97+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?x?x2xi32>>) -> !fir.ref<!fir.array<?x?x2xi32>>
98+
! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : (!fir.ref<!fir.array<?x?x2xi32>>) -> !fir.heap<!fir.array<?x?x2xi32>>
99+
! CHECK: fir.freemem %[[CAST]] : !fir.heap<!fir.array<?x?x2xi32>>
100+
! CHECK: acc.terminator
77101
! CHECK: }
78102

79103
! CHECK-LABEL: acc.private.recipe @privatization_ref_box_ptr_Uxi32 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> init {
@@ -89,6 +113,13 @@
89113
! CHECK: %[[CONV:.*]] = fir.convert %[[DECLAREBOX]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.array<?xi32>>>
90114
! CHECK: fir.store %[[DECLARE]]#0 to %[[CONV]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
91115
! CHECK: acc.yield %[[DECLAREBOX]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
116+
! CHECK: } destroy {
117+
! CHECK: ^bb0(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>):
118+
! CHECK: %[[LOAD:.*]] = fir.load %arg1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
119+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.ptr<!fir.array<?xi32>>
120+
! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : (!fir.ptr<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>>
121+
! CHECK: fir.freemem %[[CAST]] : !fir.heap<!fir.array<?xi32>>
122+
! CHECK: acc.terminator
92123
! CHECK: }
93124

94125
! CHECK-LABEL: @privatization_ref_box_heap_i32 : !fir.ref<!fir.box<!fir.heap<i32>>> init {
@@ -99,6 +130,12 @@
99130
! CHECK: %[[BOX:.*]] = fir.embox %[[ALLOCMEM]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>>
100131
! CHECK: fir.store %[[BOX]] to %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
101132
! CHECK: acc.yield %[[DECLARE]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
133+
! CHECK: } destroy {
134+
! CHECK: ^bb0(%arg0: !fir.ref<!fir.box<!fir.heap<i32>>>, %arg1: !fir.ref<!fir.box<!fir.heap<i32>>>):
135+
! CHECK: %[[LOAD:.*]] = fir.load %arg1 : !fir.ref<!fir.box<!fir.heap<i32>>>
136+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32>
137+
! CHECK: fir.freemem %[[ADDR]] : !fir.heap<i32>
138+
! CHECK: acc.terminator
102139
! CHECK: }
103140

104141
! CHECK-LABEL: acc.private.recipe @privatization_ref_box_heap_Uxi32 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> init {
@@ -114,6 +151,12 @@
114151
! CHECK: %[[CONV:.*]] = fir.convert %[[DECLAREBOX]]#0 : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.array<?xi32>>>
115152
! CHECK: fir.store %[[DECLARE]]#0 to %[[CONV]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
116153
! CHECK: acc.yield %[[DECLAREBOX]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
154+
! CHECK: } destroy {
155+
! CHECK: ^bb0(%arg0: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, %arg1: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>):
156+
! CHECK: %[[LOAD:.*]] = fir.load %arg1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
157+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
158+
! CHECK: fir.freemem %[[ADDR]] : !fir.heap<!fir.array<?xi32>>
159+
! CHECK: acc.terminator
117160
! CHECK: }
118161

119162
! CHECK-LABEL: acc.private.recipe @privatization_box_Uxi32 : !fir.box<!fir.array<?xi32>> init {
@@ -124,6 +167,12 @@
124167
! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xi32>, %0#1 {bindc_name = ".tmp", uniq_name = ""}
125168
! CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[TEMP]](%[[SHAPE]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xi32>>, !fir.heap<!fir.array<?xi32>>)
126169
! CHECK: acc.yield %[[DECLARE:.*]]#0 : !fir.box<!fir.array<?xi32>>
170+
! CHECK: } destroy {
171+
! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box<!fir.array<?xi32>>, %[[ARG1:.*]]: !fir.box<!fir.array<?xi32>>):
172+
! CHECK: %[[ADDR:.*]] = fir.box_addr %[[ARG1]] : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
173+
! CHECK: %[[CAST:.*]] = fir.convert %[[ADDR]] : (!fir.ref<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>>
174+
! CHECK: fir.freemem %[[CAST]] : !fir.heap<!fir.array<?xi32>>
175+
! CHECK: acc.terminator
127176
! CHECK: }
128177

129178
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_section_lb50.ub99_ref_50xf32 : !fir.ref<!fir.array<50xf32>> init {
@@ -140,6 +189,7 @@
140189
! CHECK: %[[DES_SRC:.*]] = hlfir.designate %[[DECL_SRC]]#0 shape %[[SHAPE:.*]] : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>>
141190
! CHECK: %[[DES_DST:.*]] = hlfir.designate %[[DECL_DST]]#0 shape %[[SHAPE:.*]] : (!fir.ref<!fir.array<50xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<50xf32>>
142191
! CHECK: hlfir.assign %[[DES_SRC]] to %[[DES_DST]] : !fir.ref<!fir.array<50xf32>>, !fir.ref<!fir.array<50xf32>>
192+
! CHECK: acc.terminator
143193
! CHECK: }
144194

145195
! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_100xf32 : !fir.ref<!fir.array<100xf32>> init {

0 commit comments

Comments
 (0)