diff --git a/flang/include/flang/Lower/Allocatable.h b/flang/include/flang/Lower/Allocatable.h index 8bfb6fdafd128..d3c16de377c1d 100644 --- a/flang/include/flang/Lower/Allocatable.h +++ b/flang/include/flang/Lower/Allocatable.h @@ -57,6 +57,11 @@ void genDeallocateBox(AbstractConverter &converter, const fir::MutableBoxValue &box, mlir::Location loc, mlir::Value declaredTypeDesc = {}); +/// Deallocate an allocatable if it is allocated at the end of its lifetime. +void genDeallocateIfAllocated(AbstractConverter &converter, + const fir::MutableBoxValue &box, + mlir::Location loc); + /// Create a MutableBoxValue for an allocatable or pointer entity. /// If the variables is a local variable that is not a dummy, it will be /// initialized to unallocated/diassociated status. diff --git a/flang/include/flang/Optimizer/Builder/MutableBox.h b/flang/include/flang/Optimizer/Builder/MutableBox.h index 1a67dbfa32314..8cd8f28dd9a10 100644 --- a/flang/include/flang/Optimizer/Builder/MutableBox.h +++ b/flang/include/flang/Optimizer/Builder/MutableBox.h @@ -120,10 +120,11 @@ void finalizeRealloc(fir::FirOpBuilder &builder, mlir::Location loc, bool takeLboundsIfRealloc, const MutableBoxReallocation &realloc); -/// Finalize a mutable box if it is allocated or associated. This includes both -/// calling the finalizer, if any, and deallocating the storage. -void genFinalization(fir::FirOpBuilder &builder, mlir::Location loc, - const fir::MutableBoxValue &box); +/// Deallocate a mutable box with fir.freemem if it is allocated or associated. +/// This only deallocates the storage and does not call finalization, the +/// mutable box is not nullified. +void genFreememIfAllocated(fir::FirOpBuilder &builder, mlir::Location loc, + const fir::MutableBoxValue &box); void genInlinedAllocation(fir::FirOpBuilder &builder, mlir::Location loc, const fir::MutableBoxValue &box, @@ -131,8 +132,10 @@ void genInlinedAllocation(fir::FirOpBuilder &builder, mlir::Location loc, mlir::ValueRange lenParams, llvm::StringRef allocName, bool mustBeHeap = false); -mlir::Value genInlinedDeallocate(fir::FirOpBuilder &builder, mlir::Location loc, - const fir::MutableBoxValue &box); +/// Deallocate an mutable box storage with fir.freemem without calling any +/// final procedures. The mutable box is not nullified. +mlir::Value genFreemem(fir::FirOpBuilder &builder, mlir::Location loc, + const fir::MutableBoxValue &box); /// When the MutableBoxValue was passed as a fir.ref to a call that may /// have modified it, update the MutableBoxValue according to the diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp index 67324e18ef605..a05f06aead173 100644 --- a/flang/lib/Lower/Allocatable.cpp +++ b/flang/lib/Lower/Allocatable.cpp @@ -746,7 +746,7 @@ static mlir::Value genDeallocate(fir::FirOpBuilder &builder, mlir::Location loc, if (!box.isDerived() && !box.isPolymorphic() && !box.isUnlimitedPolymorphic() && !errorManager.hasStatSpec() && !useAllocateRuntime) { - return fir::factory::genInlinedDeallocate(builder, loc, box); + return fir::factory::genFreemem(builder, loc, box); } // Use runtime calls to deallocate descriptor cases. Sync MutableBoxValue // with its descriptor before and after calls if needed. @@ -770,6 +770,26 @@ void Fortran::lower::genDeallocateBox( genDeallocate(builder, loc, box, errorManager, declaredTypeDesc); } +void Fortran::lower::genDeallocateIfAllocated( + Fortran::lower::AbstractConverter &converter, + const fir::MutableBoxValue &box, mlir::Location loc) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mlir::Value isAllocated = + fir::factory::genIsAllocatedOrAssociatedTest(builder, loc, box); + builder.genIfThen(loc, isAllocated) + .genThen([&]() { + if (mlir::Type eleType = box.getEleTy(); + eleType.isa() && box.isPolymorphic()) { + mlir::Value declaredTypeDesc = builder.create( + loc, mlir::TypeAttr::get(eleType)); + genDeallocateBox(converter, box, loc, declaredTypeDesc); + } else { + genDeallocateBox(converter, box, loc); + } + }) + .end(); +} + static void preDeallocationAction(Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder, mlir::Value beginOpValue, @@ -813,12 +833,13 @@ void Fortran::lower::genDeallocateStmt( genMutableBoxValue(converter, loc, allocateObject); mlir::Value declaredTypeDesc = {}; if (box.isPolymorphic()) { - assert(symbol.GetType()); - if (const Fortran::semantics::DerivedTypeSpec *derivedTypeSpec = - symbol.GetType()->AsDerived()) { - declaredTypeDesc = - Fortran::lower::getTypeDescAddr(converter, loc, *derivedTypeSpec); - } + mlir::Type eleType = box.getEleTy(); + if (eleType.isa()) + if (const Fortran::semantics::DerivedTypeSpec *derivedTypeSpec = + symbol.GetType()->AsDerived()) { + declaredTypeDesc = + Fortran::lower::getTypeDescAddr(converter, loc, *derivedTypeSpec); + } } mlir::Value beginOpValue = genDeallocate(builder, loc, box, errorManager, declaredTypeDesc); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 4d3fcd837268d..2fb3c2c3818d4 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -706,14 +706,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { return; } // deallocate allocated in createHostAssociateVarClone value - mlir::Value needs_dealloc = - fir::factory::genIsAllocatedOrAssociatedTest(*builder, loc, - new_box); - builder->genIfThen(loc, needs_dealloc) - .genThen([&]() { - Fortran::lower::genDeallocateBox(*this, new_box, loc); - }) - .end(); + Fortran::lower::genDeallocateIfAllocated(*this, new_box, loc); }, [&](const auto &) -> void { // Do nothing diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index fbf8eac642af2..59d059e27cf1a 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -461,10 +461,13 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult( allocatedResult->match( [&](const fir::MutableBoxValue &box) { if (box.isAllocatable() && !cleanupWithDestroy) { - // 9.7.3.2 point 4. Finalize allocatables. + // 9.7.3.2 point 4. Deallocate allocatable results. Note that + // finalization was done independently by calling + // genDerivedTypeDestroy above and is not triggered by this inline + // deallocation. fir::FirOpBuilder *bldr = &converter.getFirOpBuilder(); stmtCtx.attachCleanup([bldr, loc, box]() { - fir::factory::genFinalization(*bldr, loc, box); + fir::factory::genFreememIfAllocated(*bldr, loc, box); }); } }, diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index c1c6e162ddbaa..8788e82b59a8d 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -2646,26 +2646,14 @@ class ScalarExprLowering { } // Passing a POINTER to a POINTER, or an ALLOCATABLE to an ALLOCATABLE. fir::MutableBoxValue mutableBox = genMutableBoxValue(*expr); + if (fir::isAllocatableType(argTy) && arg.isIntentOut() && + Fortran::semantics::IsBindCProcedure(*procRef.proc().GetSymbol())) + Fortran::lower::genDeallocateIfAllocated(converter, mutableBox, loc); mlir::Value irBox = fir::factory::getMutableIRBox(builder, loc, mutableBox); caller.placeInput(arg, irBox); if (arg.mayBeModifiedByCall()) mutableModifiedByCall.emplace_back(std::move(mutableBox)); - if (fir::isAllocatableType(argTy) && arg.isIntentOut() && - Fortran::semantics::IsBindCProcedure(*procRef.proc().GetSymbol())) { - if (mutableBox.isDerived() || mutableBox.isPolymorphic() || - mutableBox.isUnlimitedPolymorphic()) { - mlir::Value isAlloc = fir::factory::genIsAllocatedOrAssociatedTest( - builder, loc, mutableBox); - builder.genIfThen(loc, isAlloc) - .genThen([&]() { - Fortran::lower::genDeallocateBox(converter, mutableBox, loc); - }) - .end(); - } else { - Fortran::lower::genDeallocateBox(converter, mutableBox, loc); - } - } continue; } if (arg.passBy == PassBy::BaseAddress || arg.passBy == PassBy::BoxChar || diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index d0a84eff1ebab..1d74cf2daf5f3 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -749,40 +749,17 @@ static void deallocateIntentOut(Fortran::lower::AbstractConverter &converter, } mlir::Location loc = converter.getCurrentLocation(); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); - auto genDeallocateWithTypeDesc = [&]() { - if (mutBox->isDerived() || mutBox->isPolymorphic() || - mutBox->isUnlimitedPolymorphic()) { - mlir::Value isAlloc = fir::factory::genIsAllocatedOrAssociatedTest( - builder, loc, *mutBox); - builder.genIfThen(loc, isAlloc) - .genThen([&]() { - if (mutBox->isPolymorphic()) { - mlir::Value declaredTypeDesc; - assert(sym.GetType()); - if (const Fortran::semantics::DerivedTypeSpec - *derivedTypeSpec = sym.GetType()->AsDerived()) { - declaredTypeDesc = Fortran::lower::getTypeDescAddr( - converter, loc, *derivedTypeSpec); - } - genDeallocateBox(converter, *mutBox, loc, declaredTypeDesc); - } else { - genDeallocateBox(converter, *mutBox, loc); - } - }) - .end(); - } else { - genDeallocateBox(converter, *mutBox, loc); - } - }; if (Fortran::semantics::IsOptional(sym)) { auto isPresent = builder.create( loc, builder.getI1Type(), fir::getBase(extVal)); builder.genIfThen(loc, isPresent) - .genThen([&]() { genDeallocateWithTypeDesc(); }) + .genThen([&]() { + Fortran::lower::genDeallocateIfAllocated(converter, *mutBox, loc); + }) .end(); } else { - genDeallocateWithTypeDesc(); + Fortran::lower::genDeallocateIfAllocated(converter, *mutBox, loc); } } } diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp index e7eac8bf5270a..61813f6b71dc5 100644 --- a/flang/lib/Optimizer/Builder/MutableBox.cpp +++ b/flang/lib/Optimizer/Builder/MutableBox.cpp @@ -454,12 +454,10 @@ mlir::Value fir::factory::genIsNotAllocatedOrAssociatedTest( return builder.genIsNullAddr(loc, addr); } -/// Generate finalizer call and inlined free. This does not check that the +/// Call freemem. This does not check that the /// address was allocated. -static void genFinalizeAndFree(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value addr) { - // TODO: call finalizer if any. - +static void genFreemem(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value addr) { // A heap (ALLOCATABLE) object may have been converted to a ptr (POINTER), // so make sure the heap type is restored before deallocation. auto cast = builder.createConvert( @@ -467,16 +465,16 @@ static void genFinalizeAndFree(fir::FirOpBuilder &builder, mlir::Location loc, builder.create(loc, cast); } -void fir::factory::genFinalization(fir::FirOpBuilder &builder, - mlir::Location loc, - const fir::MutableBoxValue &box) { +void fir::factory::genFreememIfAllocated(fir::FirOpBuilder &builder, + mlir::Location loc, + const fir::MutableBoxValue &box) { auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); auto isAllocated = builder.genIsNotNullAddr(loc, addr); auto ifOp = builder.create(loc, isAllocated, /*withElseRegion=*/false); auto insPt = builder.saveInsertionPoint(); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - genFinalizeAndFree(builder, loc, addr); + ::genFreemem(builder, loc, addr); builder.restoreInsertionPoint(insPt); } @@ -753,12 +751,11 @@ void fir::factory::genInlinedAllocation( fir::MustBeHeapAttr::get(builder.getContext(), mustBeHeap)); } -mlir::Value -fir::factory::genInlinedDeallocate(fir::FirOpBuilder &builder, - mlir::Location loc, - const fir::MutableBoxValue &box) { +mlir::Value fir::factory::genFreemem(fir::FirOpBuilder &builder, + mlir::Location loc, + const fir::MutableBoxValue &box) { auto addr = MutablePropertyReader(builder, loc, box).readBaseAddress(); - genFinalizeAndFree(builder, loc, addr); + ::genFreemem(builder, loc, addr); MutablePropertyWriter{builder, loc, box}.setUnallocatedStatus(); return addr; } @@ -909,8 +906,7 @@ void fir::factory::finalizeRealloc(fir::FirOpBuilder &builder, auto heap = fir::getBase(realloc.newValue); auto extents = fir::factory::getExtents(loc, builder, realloc.newValue); builder.genIfThen(loc, realloc.oldAddressWasAllocated) - .genThen( - [&]() { genFinalizeAndFree(builder, loc, realloc.oldAddress); }) + .genThen([&]() { ::genFreemem(builder, loc, realloc.oldAddress); }) .end(); MutablePropertyWriter{builder, loc, box}.updateMutableBox( heap, lbs, extents, lengths); diff --git a/flang/test/Lower/Intrinsics/system_clock.f90 b/flang/test/Lower/Intrinsics/system_clock.f90 index 8db4629c24efa..37ed097e9a5df 100644 --- a/flang/test/Lower/Intrinsics/system_clock.f90 +++ b/flang/test/Lower/Intrinsics/system_clock.f90 @@ -53,13 +53,13 @@ subroutine ss(count) ! CHECK: fir.store %[[V_29]] to %arg0 : !fir.ref ! CHECK: } ! CHECK: %[[V_12:[0-9]+]] = fir.convert %[[V_9]] : (!fir.ptr) -> i64 - ! CHECK: %[[V_13:[0-9]+]] = arith.cmpi ne, %[[V_12]], %c0{{.*}}_i64 : i64 + ! CHECK: %[[V_13:[0-9]+]] = arith.cmpi ne, %[[V_12]], %c0{{.*}} : i64 ! CHECK: fir.if %[[V_13]] { - ! CHECK: %[[V_29]] = fir.call @_FortranASystemClockCountRate(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 + ! CHECK: %[[V_29:[0-9]+]] = fir.call @_FortranASystemClockCountRate(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 ! CHECK: fir.store %[[V_29]] to %[[V_9]] : !fir.ptr ! CHECK: } ! CHECK: %[[V_14:[0-9]+]] = fir.convert %[[V_10]] : (!fir.heap) -> i64 - ! CHECK: %[[V_15:[0-9]+]] = arith.cmpi ne, %[[V_14]], %c0{{.*}}_i64_0 : i64 + ! CHECK: %[[V_15:[0-9]+]] = arith.cmpi ne, %[[V_14]], %c0{{.*}} : i64 ! CHECK: fir.if %[[V_15]] { ! CHECK: %[[V_29]] = fir.call @_FortranASystemClockCountMax(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 ! CHECK: fir.store %[[V_29]] to %[[V_10]] : !fir.heap @@ -77,24 +77,24 @@ subroutine ss(count) ! CHECK: %[[V_39:[0-9]+]] = fir.call @_FortranAioOutputInteger64(%[[V_31]], %[[V_38]]) {{.*}}: (!fir.ref, i64) -> i1 ! CHECK: %[[V_40:[0-9]+]] = fir.call @_FortranAioEndIoStatement(%[[V_31]]) {{.*}}: (!fir.ref) -> i32 ! CHECK: } else { - ! CHECK: %[[V_29]] = fir.load %[[V_4]] : !fir.ref> + ! CHECK: %[[V_29:[0-9]+]] = fir.load %[[V_4]] : !fir.ref> ! CHECK: %[[V_30:[0-9]+]] = fir.load %[[V_1]] : !fir.ref> - ! CHECK: %[[V_31]] = fir.convert %[[V_29]] : (!fir.ptr) -> i64 - ! CHECK: %[[V_32]] = arith.cmpi ne, %[[V_31]], %c0{{.*}}_i64_3 : i64 + ! CHECK: %[[V_31:[0-9]+]] = fir.convert %[[V_29]] : (!fir.ptr) -> i64 + ! CHECK: %[[V_32:[0-9]+]] = arith.cmpi ne, %[[V_31]], %c0{{.*}} : i64 ! CHECK: fir.if %[[V_32]] { ! CHECK: %[[V_45:[0-9]+]] = fir.call @_FortranASystemClockCountRate(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 ! CHECK: fir.store %[[V_45]] to %[[V_29]] : !fir.ptr ! CHECK: } - ! CHECK: %[[V_33]] = fir.convert %[[V_30]] : (!fir.heap) -> i64 - ! CHECK: %[[V_34]] = arith.cmpi ne, %[[V_33]], %c0{{.*}}_i64_4 : i64 + ! CHECK: %[[V_33:[0-9]+]] = fir.convert %[[V_30]] : (!fir.heap) -> i64 + ! CHECK: %[[V_34:[0-9]+]] = arith.cmpi ne, %[[V_33]], %c0{{.*}} : i64 ! CHECK: fir.if %[[V_34]] { ! CHECK: %[[V_45]] = fir.call @_FortranASystemClockCountMax(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 ! CHECK: fir.store %[[V_45]] to %[[V_30]] : !fir.heap ! CHECK: } - ! CHECK: %[[V_37]] = fir.call @_FortranAioBeginExternalListOutput - ! CHECK: %[[V_38]] = fir.load %[[V_4]] : !fir.ref> - ! CHECK: %[[V_39]] = fir.load %[[V_38]] : !fir.ptr - ! CHECK: %[[V_40]] = fir.call @_FortranAioOutputInteger64(%[[V_37]], %[[V_39]]) {{.*}}: (!fir.ref, i64) -> i1 + ! CHECK: %[[V_37:[0-9]+]] = fir.call @_FortranAioBeginExternalListOutput + ! CHECK: %[[V_38:[0-9]+]] = fir.load %[[V_4]] : !fir.ref> + ! CHECK: %[[V_39:[0-9]+]] = fir.load %[[V_38]] : !fir.ptr + ! CHECK: %[[V_40:[0-9]+]] = fir.call @_FortranAioOutputInteger64(%[[V_37]], %[[V_39]]) {{.*}}: (!fir.ref, i64) -> i1 ! CHECK: %[[V_41:[0-9]+]] = fir.load %[[V_1]] : !fir.ref> ! CHECK: %[[V_42:[0-9]+]] = fir.load %[[V_41]] : !fir.heap ! CHECK: %[[V_43:[0-9]+]] = fir.call @_FortranAioOutputInteger64(%[[V_37]], %[[V_42]]) {{.*}}: (!fir.ref, i64) -> i1 @@ -120,13 +120,13 @@ subroutine ss(count) ! CHECK: fir.store %[[V_29]] to %arg0 : !fir.ref ! CHECK: } ! CHECK: %[[V_24:[0-9]+]] = fir.convert %[[V_21]] : (!fir.ptr) -> i64 - ! CHECK: %[[V_25:[0-9]+]] = arith.cmpi ne, %[[V_24]], %c0{{.*}}_i64_1 : i64 + ! CHECK: %[[V_25:[0-9]+]] = arith.cmpi ne, %[[V_24]], %c0{{.*}} : i64 ! CHECK: fir.if %[[V_25]] { ! CHECK: %[[V_29]] = fir.call @_FortranASystemClockCountRate(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 ! CHECK: fir.store %[[V_29]] to %[[V_21]] : !fir.ptr ! CHECK: } ! CHECK: %[[V_26:[0-9]+]] = fir.convert %[[V_22]] : (!fir.heap) -> i64 - ! CHECK: %[[V_27:[0-9]+]] = arith.cmpi ne, %[[V_26]], %c0{{.*}}_i64_2 : i64 + ! CHECK: %[[V_27:[0-9]+]] = arith.cmpi ne, %[[V_26]], %c0{{.*}} : i64 ! CHECK: fir.if %[[V_27]] { ! CHECK: %[[V_29]] = fir.call @_FortranASystemClockCountMax(%c8{{.*}}_i32) {{.*}}: (i32) -> i64 ! CHECK: fir.store %[[V_29]] to %[[V_22]] : !fir.heap diff --git a/flang/test/Lower/OpenMP/FIR/parallel-private-clause.f90 b/flang/test/Lower/OpenMP/FIR/parallel-private-clause.f90 index e9d9218702cc5..8d288f6483493 100644 --- a/flang/test/Lower/OpenMP/FIR/parallel-private-clause.f90 +++ b/flang/test/Lower/OpenMP/FIR/parallel-private-clause.f90 @@ -146,20 +146,20 @@ subroutine private_clause_allocatable() !FIRDialect-DAG: omp.parallel { !FIRDialect-DAG: [[TMP203:%.*]] = fir.alloca !fir.box> {bindc_name = "x5", pinned, uniq_name = "{{.*}}Ex5"} -!FIRDialect-DAG: fir.if %7 { +!FIRDialect-DAG: fir.if %{{.*}} { -!FIRDialect-DAG: fir.store %13 to [[TMP203]] : !fir.ref>> +!FIRDialect-DAG: fir.store %{{.*}} to [[TMP203]] : !fir.ref>> !FIRDialect-DAG: } else { -!FIRDialect-DAG: fir.store %13 to [[TMP203]] : !fir.ref>> +!FIRDialect-DAG: fir.store %{{.*}} to [[TMP203]] : !fir.ref>> !FIRDialect-DAG: } !FIRDialect-DAG: fir.call @_QFprivate_clause_real_call_allocatablePhelper_private_clause_real_call_allocatable([[TMP203]]) fastmath : (!fir.ref>>) -> () -!FIRDialect-DAG: %8 = fir.load [[TMP203]] : !fir.ref>> +!FIRDialect-DAG: %{{.*}} = fir.load [[TMP203]] : !fir.ref>> -!FIRDialect-DAG: fir.if %11 { -!FIRDialect-DAG: %12 = fir.load [[TMP203]] : !fir.ref>> +!FIRDialect-DAG: fir.if %{{.*}} { +!FIRDialect-DAG: %{{.*}} = fir.load [[TMP203]] : !fir.ref>> -!FIRDialect-DAG: fir.store %15 to [[TMP203]] : !fir.ref>> +!FIRDialect-DAG: fir.store %{{.*}} to [[TMP203]] : !fir.ref>> !FIRDialect-DAG: } !FIRDialect-DAG: omp.terminator !FIRDialect-DAG: } @@ -353,9 +353,9 @@ subroutine simple_loop_3 subroutine simd_loop_1 integer :: i real, allocatable :: r; - ! IRDialect: [[R:%.*]] = fir.alloca !fir.box> {bindc_name = "r", pinned, uniq_name = "{{.*}}Er"} - ! IRDialect: fir.store {{%.*}} to [[R]] : !fir.ref>> - ! IRDialect: fir.store {{%.*}} to [[R]] : !fir.ref>> + ! FIRDialect: [[R:%.*]] = fir.alloca !fir.box> {bindc_name = "r", pinned, uniq_name = "{{.*}}Er"} + ! FIRDialect: fir.store {{%.*}} to [[R]] : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to [[R]] : !fir.ref>> ! FIRDialect: %[[LB:.*]] = arith.constant 1 : i32 ! FIRDialect: %[[UB:.*]] = arith.constant 9 : i32 diff --git a/flang/test/Lower/intentout-deallocate.f90 b/flang/test/Lower/intentout-deallocate.f90 index f2664188092d9..81207a09b2b3f 100644 --- a/flang/test/Lower/intentout-deallocate.f90 +++ b/flang/test/Lower/intentout-deallocate.f90 @@ -51,12 +51,19 @@ subroutine sub1(a) ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> -! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> -! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> -! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> -! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: } subroutine sub2() integer, allocatable :: a(:) @@ -69,12 +76,18 @@ subroutine sub2() ! CHECK-LABEL: func.func @_QMmod1Psub2() ! CHECK: %[[BOX:.*]] = fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QMmod1Fsub2Ea"} ! CHECK: %[[BOX_ALLOC:.*]] = fir.alloca !fir.heap> {uniq_name = "_QMmod1Fsub2Ea.addr"} +! CHECK: %[[BOX_ADDR:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[LOAD:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> +! CHECK: fir.freemem %[[LOAD]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: fir.store %[[ZERO]] to %[[BOX_ALLOC]] : !fir.ref>> +! CHECK: } ! CHECK: %[[LOAD:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> ! CHECK: %{{.*}} = fir.embox %[[LOAD]](%{{.*}}) : (!fir.heap>, !fir.shapeshift< -! CHECK: %[[LOAD:.*]] = fir.load %[[BOX_ALLOC]] : !fir.ref>> -! CHECK: fir.freemem %[[LOAD]] : !fir.heap> -! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! CHECK: fir.store %[[ZERO]] to %[[BOX_ALLOC]] : !fir.ref>> ! CHECK: fir.call @sub3(%[[BOX]]) {{.*}}: (!fir.ref>>>) -> () subroutine sub4() @@ -147,12 +160,19 @@ subroutine sub9(a) ! CHECK: fir.if %[[IS_PRESENT]] { ! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> -! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> -! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> -! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> -! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: } ! CHECK: } subroutine sub10(a) @@ -165,12 +185,19 @@ subroutine sub10(a) ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> -! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> -! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> -! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> -! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: } ! CHECK-LABEL: func.func @_QMmod1Psub11() { ! CHECK-NOT: fir.freemem @@ -184,23 +211,37 @@ subroutine sub12(a) ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> -! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> -! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> -! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> -! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: } ! CHECK-LABEL: func.func @_QMmod1Psub13( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>>> {fir.bindc_name = "a"}) { ! CHECK: %[[LOAD:.*]] = fir.load %[[ARG0]] : !fir.ref>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box>>) -> !fir.heap> -! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> -! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> -! CHECK: %[[C0:.*]] = arith.constant 0 : index -! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> -! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> -! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR_PTR:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.heap>) -> i64 +! CHECK: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 +! CHECK: fir.if %[[IS_ALLOCATED]] { +! CHECK: %[[BOX:.*]] = fir.load %[[ARG0]] : !fir.ref>>> +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.heap> +! CHECK: fir.freemem %[[BOX_ADDR]] : !fir.heap> +! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.heap> +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box>> +! CHECK: fir.store %[[EMBOX]] to %[[ARG0]] : !fir.ref>>> +! CHECK: } subroutine sub14(p) @@ -215,9 +256,9 @@ subroutine sub14(p) ! CHECK: %[[C0:.*]] = arith.constant 0 : i64 ! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 ! CHECK: fir.if %[[IS_ALLOCATED]] { -! CHECK: %[[TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMmod1Tt{a:i32}> +! CHECK: %[[TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMmod1Tt{a:i32}> ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_NONE:.*]] = fir.convert %[[TYPE_DESC]] : (!fir.tdesc>) -> !fir.ref +! CHECK: %[[TYPE_NONE:.*]] = fir.convert %[[TYPE_DESC]] : (!fir.tdesc>) -> !fir.ref ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%[[BOX_NONE]], %[[TYPE_NONE]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: } @@ -233,7 +274,7 @@ subroutine sub15(p) ! CHECK: %[[C0:.*]] = arith.constant 0 : i64 ! CHECK: %[[IS_ALLOCATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_PTR]], %[[C0]] : i64 ! CHECK: fir.if %[[IS_ALLOCATED]] { -! CHECK: %[[NULL_TYPE_DESC:.*]] = fir.zero_bits !fir.ref +! CHECK: %[[NULL_TYPE_DESC:.*]] = fir.zero_bits !fir.ref ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.ref>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%[[BOX_NONE]], %[[NULL_TYPE_DESC]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: } @@ -254,10 +295,9 @@ subroutine sub16(p) ! CHECK: fir.if %[[IS_ALLOCATED]] { ! CHECK: %[[TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMmod1Tt{a:i32}> ! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.ref>>>) -> !fir.ref> -! CHECK: %[[TYPE_NONE:.*]] = fir.convert %[[TYPE_DESC]] : (!fir.tdesc>) -> !fir.ref +! CHECK: %[[TYPE_NONE:.*]] = fir.convert %[[TYPE_DESC]] : (!fir.tdesc>) -> !fir.ref ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%[[BOX_NONE]], %[[TYPE_NONE]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.ref, i1, !fir.box, !fir.ref, i32) -> i32 ! CHECK: } ! CHECK: } end module -