From edd76804c665bfe97c703a8fedbd5fc8c7c4ba70 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Thu, 9 Oct 2025 12:49:26 -0400 Subject: [PATCH 1/5] Use the namelist item descriptor if it is local polymorphic entity. --- flang/lib/Lower/IO.cpp | 21 ++++++++------ flang/test/Lower/namelist.f90 | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 98dc78f625b9e..8be5f7c8af115 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -526,14 +526,19 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, } else { const auto expr = Fortran::evaluate::AsGenericExpr(s); fir::ExtendedValue exv = converter.genExprAddr(*expr, stmtCtx); - mlir::Type type = fir::getBase(exv).getType(); - if (mlir::Type baseTy = fir::dyn_cast_ptrOrBoxEleTy(type)) - type = baseTy; - fir::BoxType boxType = fir::BoxType::get(fir::PointerType::get(type)); - descAddr = builder.createTemporary(loc, boxType); - fir::MutableBoxValue box = fir::MutableBoxValue(descAddr, {}, {}); - fir::factory::associateMutableBox(builder, loc, box, exv, - /*lbounds=*/{}); + descAddr = fir::getBase(exv); + mlir::Type type = descAddr.getType(); + + // Don't need temp descriptor if the namelist item is polymorphic. + if (!mlir::isa(type)) { + if (mlir::Type baseTy = fir::dyn_cast_ptrOrBoxEleTy(type)) + type = baseTy; + fir::BoxType boxType = fir::BoxType::get(fir::PointerType::get(type)); + descAddr = builder.createTemporary(loc, boxType); + fir::MutableBoxValue box = fir::MutableBoxValue(descAddr, {}, {}); + fir::factory::associateMutableBox(builder, loc, box, exv, + /*lbounds=*/{}); + } } descAddr = builder.createConvert(loc, descRefTy, descAddr); list = fir::InsertValueOp::create(builder, loc, listTy, list, descAddr, diff --git a/flang/test/Lower/namelist.f90 b/flang/test/Lower/namelist.f90 index 770af46eea744..e7baa527faa52 100644 --- a/flang/test/Lower/namelist.f90 +++ b/flang/test/Lower/namelist.f90 @@ -123,6 +123,57 @@ subroutine global_pointer write(10, nml=mygroup) end +module m + type base + real :: r1 + end type + interface write(formatted) + subroutine writeformatted(dtv, unit, iotype, v_list, iostat, iomsg ) + import base + class(base), intent(in) :: dtv + integer, intent(in) :: unit + character(*), intent(in) :: iotype + integer, intent(in) :: v_list(:) + integer, intent(out) :: iostat + character(*), intent(inout) :: iomsg + end subroutine + end interface +end module + +! CHECK-LABEL: c.func @_QPlocal_poly_namelist +subroutine local_poly_namelist + use m + class(base), allocatable :: b1 + ! CHECK: %[[V_1:[0-9]+]] = fir.alloca !fir.class>> {bindc_name = "b1", uniq_name = "_QFlocal_poly_namelistEb1"} + ! CHECK: %[[V_4:[0-9]+]] = fir.declare %[[V_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_poly_namelistEb1"} : (!fir.ref>>>) -> !fir.ref>>> + ! CHECK: %[[V_7:[0-9]+]] = fir.call @_FortranAioBeginExternalListOutput + ! CHECK: %[[V_8:[0-9]+]] = fir.alloca !fir.array<1xtuple, !fir.ref>>> + ! CHECK: %[[V_9:[0-9]+]] = fir.undefined !fir.array<1xtuple, !fir.ref>>> + ! CHECK: %[[V_10:[0-9]+]] = fir.address_of(@_QQclX623100) : !fir.ref> + ! CHECK: %[[V_11:[0-9]+]] = fir.convert %[[V_10]] : (!fir.ref>) -> !fir.ref + ! CHECK: %[[V_12:[0-9]+]] = fir.insert_value %[[V_9]], %[[V_11]], [0 : index, 0 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref>>> + ! CHECK: %[[V_13:[0-9]+]] = fir.load %[[V_4]] : !fir.ref>>> + ! CHECK: %[[V_14:[0-9]+]] = fir.convert %[[V_13]] : (!fir.class>>) -> !fir.ref> + ! CHECK: %[[V_15:[0-9]+]] = fir.insert_value %[[V_12]], %[[V_14]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref>) -> !fir.array<1xtuple, !fir.ref>>> + ! CHECK: fir.store %[[V_15]] to %[[V_8]] : !fir.ref, !fir.ref>>>> + ! CHECK: %[[V_16:[0-9]+]] = fir.alloca tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> + ! CHECK: %[[V_17:[0-9]+]] = fir.undefined tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> + ! CHECK: %[[V_18:[0-9]+]] = fir.address_of(@_QQclX6D7967726F757000) : !fir.ref> + ! CHECK: %[[V_19:[0-9]+]] = fir.convert %[[V_18]] : (!fir.ref>) -> !fir.ref + ! CHECK: %[[V_20:[0-9]+]] = fir.insert_value %[[V_17]], %[[V_19]], [0 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> + ! CHECK: %[[V_21:[0-9]+]] = fir.insert_value %[[V_20]], %c1_i64, [1 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, i64) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> + ! CHECK: %[[V_22:[0-9]+]] = fir.insert_value %[[V_21]], %[[V_8]], [2 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref, !fir.ref>>>>) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> + ! CHECK: %[[V_23:[0-9]+]] = fir.address_of(@_QQFlocal_poly_namelist.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> + ! CHECK: %[[V_24:[0-9]+]] = fir.convert %[[V_23]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref + ! CHECK: %[[V_25:[0-9]+]] = fir.insert_value %[[V_22]], %[[V_24]], [3 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> + ! CHECK: fir.store %[[V_25]] to %[[V_16]] : !fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>> + ! CHECK: %[[V_26:[0-9]+]] = fir.convert %[[V_16]] : (!fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>>) -> !fir.ref> + ! CHECK: %[[V_27:[0-9]+]] = fir.call @_FortranAioOutputNamelist(%[[V_7]], %[[V_26]]) fastmath : (!fir.ref, !fir.ref>) -> i1 + ! CHECK: %[[V_28:[0-9]+]] = fir.call @_FortranAioEndIoStatement(%[[V_7]]) fastmath : (!fir.ref) -> i32 + namelist/mygroup/b1 + write(10, nml=mygroup) +end subroutine + module mmm real rrr namelist /aaa/ rrr @@ -142,3 +193,4 @@ subroutine rename_sub ! CHECK-NOT: ggg ! CHECK: fir.string_lit "aaa\00"(4) : !fir.char<1,4> + From a17543781d321da92f484227edd40133ca19e71e Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Thu, 9 Oct 2025 22:30:31 -0400 Subject: [PATCH 2/5] To address review comments. --- flang/lib/Lower/IO.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 8be5f7c8af115..356f617918d18 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -530,7 +530,9 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, mlir::Type type = descAddr.getType(); // Don't need temp descriptor if the namelist item is polymorphic. - if (!mlir::isa(type)) { + if (mlir::isa(type)) { + descRefTy = fir::BoxType::get(mlir::NoneType::get(context)); + } else { if (mlir::Type baseTy = fir::dyn_cast_ptrOrBoxEleTy(type)) type = baseTy; fir::BoxType boxType = fir::BoxType::get(fir::PointerType::get(type)); From 4452e142848f0e147a50ef6f2d46ba2d3e29e477 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Thu, 9 Oct 2025 22:41:08 -0400 Subject: [PATCH 3/5] Update the test case. --- flang/test/Lower/namelist.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flang/test/Lower/namelist.f90 b/flang/test/Lower/namelist.f90 index e7baa527faa52..6674fdff347cc 100644 --- a/flang/test/Lower/namelist.f90 +++ b/flang/test/Lower/namelist.f90 @@ -153,8 +153,8 @@ subroutine local_poly_namelist ! CHECK: %[[V_11:[0-9]+]] = fir.convert %[[V_10]] : (!fir.ref>) -> !fir.ref ! CHECK: %[[V_12:[0-9]+]] = fir.insert_value %[[V_9]], %[[V_11]], [0 : index, 0 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref>>> ! CHECK: %[[V_13:[0-9]+]] = fir.load %[[V_4]] : !fir.ref>>> - ! CHECK: %[[V_14:[0-9]+]] = fir.convert %[[V_13]] : (!fir.class>>) -> !fir.ref> - ! CHECK: %[[V_15:[0-9]+]] = fir.insert_value %[[V_12]], %[[V_14]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref>) -> !fir.array<1xtuple, !fir.ref>>> + ! CHECK: %[[V_14:[0-9]+]] = fir.convert %[[V_13]] : (!fir.class>>) -> !fir.box + ! CHECK: %[[V_15:[0-9]+]] = fir.insert_value %[[V_12]], %[[V_14]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.box) -> !fir.array<1xtuple, !fir.ref>>> ! CHECK: fir.store %[[V_15]] to %[[V_8]] : !fir.ref, !fir.ref>>>> ! CHECK: %[[V_16:[0-9]+]] = fir.alloca tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> ! CHECK: %[[V_17:[0-9]+]] = fir.undefined tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> From fc8d5ccbb77f917cb617345369b0502484a77d98 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Fri, 10 Oct 2025 23:18:31 -0400 Subject: [PATCH 4/5] To set fir::ClassType for the temporary descriptor. --- flang/lib/Lower/IO.cpp | 29 ++++++++++++------------- flang/test/Lower/namelist.f90 | 40 ++++++++++++----------------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 356f617918d18..340406919cdf2 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -524,23 +524,22 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, descAddr = builder.createConvert(loc, builder.getRefType(symType), varAddr); } else { + fir::BaseBoxType boxType; const auto expr = Fortran::evaluate::AsGenericExpr(s); fir::ExtendedValue exv = converter.genExprAddr(*expr, stmtCtx); - descAddr = fir::getBase(exv); - mlir::Type type = descAddr.getType(); - - // Don't need temp descriptor if the namelist item is polymorphic. - if (mlir::isa(type)) { - descRefTy = fir::BoxType::get(mlir::NoneType::get(context)); - } else { - if (mlir::Type baseTy = fir::dyn_cast_ptrOrBoxEleTy(type)) - type = baseTy; - fir::BoxType boxType = fir::BoxType::get(fir::PointerType::get(type)); - descAddr = builder.createTemporary(loc, boxType); - fir::MutableBoxValue box = fir::MutableBoxValue(descAddr, {}, {}); - fir::factory::associateMutableBox(builder, loc, box, exv, - /*lbounds=*/{}); - } + mlir::Type type = fir::getBase(exv).getType(); + mlir::Type eleType = type; + if (mlir::Type baseTy = fir::dyn_cast_ptrOrBoxEleTy(type)) + eleType = baseTy; + + if (mlir::isa(type)) + boxType = fir::ClassType::get(fir::PointerType::get(eleType)); + else + boxType = fir::BoxType::get(fir::PointerType::get(eleType)); + descAddr = builder.createTemporary(loc, boxType); + fir::MutableBoxValue box = fir::MutableBoxValue(descAddr, {}, {}); + fir::factory::associateMutableBox(builder, loc, box, exv, + /*lbounds=*/{}); } descAddr = builder.createConvert(loc, descRefTy, descAddr); list = fir::InsertValueOp::create(builder, loc, listTy, list, descAddr, diff --git a/flang/test/Lower/namelist.f90 b/flang/test/Lower/namelist.f90 index 6674fdff347cc..a258da1986db5 100644 --- a/flang/test/Lower/namelist.f90 +++ b/flang/test/Lower/namelist.f90 @@ -144,32 +144,20 @@ subroutine writeformatted(dtv, unit, iotype, v_list, iostat, iomsg ) subroutine local_poly_namelist use m class(base), allocatable :: b1 - ! CHECK: %[[V_1:[0-9]+]] = fir.alloca !fir.class>> {bindc_name = "b1", uniq_name = "_QFlocal_poly_namelistEb1"} - ! CHECK: %[[V_4:[0-9]+]] = fir.declare %[[V_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_poly_namelistEb1"} : (!fir.ref>>>) -> !fir.ref>>> - ! CHECK: %[[V_7:[0-9]+]] = fir.call @_FortranAioBeginExternalListOutput - ! CHECK: %[[V_8:[0-9]+]] = fir.alloca !fir.array<1xtuple, !fir.ref>>> - ! CHECK: %[[V_9:[0-9]+]] = fir.undefined !fir.array<1xtuple, !fir.ref>>> - ! CHECK: %[[V_10:[0-9]+]] = fir.address_of(@_QQclX623100) : !fir.ref> - ! CHECK: %[[V_11:[0-9]+]] = fir.convert %[[V_10]] : (!fir.ref>) -> !fir.ref - ! CHECK: %[[V_12:[0-9]+]] = fir.insert_value %[[V_9]], %[[V_11]], [0 : index, 0 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref>>> - ! CHECK: %[[V_13:[0-9]+]] = fir.load %[[V_4]] : !fir.ref>>> - ! CHECK: %[[V_14:[0-9]+]] = fir.convert %[[V_13]] : (!fir.class>>) -> !fir.box - ! CHECK: %[[V_15:[0-9]+]] = fir.insert_value %[[V_12]], %[[V_14]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.box) -> !fir.array<1xtuple, !fir.ref>>> - ! CHECK: fir.store %[[V_15]] to %[[V_8]] : !fir.ref, !fir.ref>>>> - ! CHECK: %[[V_16:[0-9]+]] = fir.alloca tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_17:[0-9]+]] = fir.undefined tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_18:[0-9]+]] = fir.address_of(@_QQclX6D7967726F757000) : !fir.ref> - ! CHECK: %[[V_19:[0-9]+]] = fir.convert %[[V_18]] : (!fir.ref>) -> !fir.ref - ! CHECK: %[[V_20:[0-9]+]] = fir.insert_value %[[V_17]], %[[V_19]], [0 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_21:[0-9]+]] = fir.insert_value %[[V_20]], %c1_i64, [1 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, i64) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_22:[0-9]+]] = fir.insert_value %[[V_21]], %[[V_8]], [2 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref, !fir.ref>>>>) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: %[[V_23:[0-9]+]] = fir.address_of(@_QQFlocal_poly_namelist.nonTbpDefinedIoTable) : !fir.ref, !fir.ref, i32, i8>>>, i1>> - ! CHECK: %[[V_24:[0-9]+]] = fir.convert %[[V_23]] : (!fir.ref, !fir.ref, i32, i8>>>, i1>>) -> !fir.ref - ! CHECK: %[[V_25:[0-9]+]] = fir.insert_value %[[V_22]], %[[V_24]], [3 : index] : (tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref>, !fir.ref) -> tuple, i64, !fir.ref, !fir.ref>>>>, !fir.ref> - ! CHECK: fir.store %[[V_25]] to %[[V_16]] : !fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>> - ! CHECK: %[[V_26:[0-9]+]] = fir.convert %[[V_16]] : (!fir.ref, i64, !fir.ref, !fir.ref>>>>, !fir.ref>>) -> !fir.ref> - ! CHECK: %[[V_27:[0-9]+]] = fir.call @_FortranAioOutputNamelist(%[[V_7]], %[[V_26]]) fastmath : (!fir.ref, !fir.ref>) -> i1 - ! CHECK: %[[V_28:[0-9]+]] = fir.call @_FortranAioEndIoStatement(%[[V_7]]) fastmath : (!fir.ref) -> i32 +! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.class>> +! CHECK: %[[V_2:[0-9]+]] = fir.alloca !fir.class>> {bindc_name = "b1", uniq_name = "_QFlocal_poly_namelistEb1"} +! CHECK: %[[V_5:[0-9]+]] = fir.declare %[[V_2]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_poly_namelistEb1"} : (!fir.ref>>>) -> !fir.ref>>> +! CHECK: %[[V_9:[0-9]+]] = fir.alloca !fir.array<1xtuple, !fir.ref>>> +! CHECK: %[[V_10:[0-9]+]] = fir.undefined !fir.array<1xtuple, !fir.ref>>> +! CHECK: %[[V_11:[0-9]+]] = fir.address_of(@_QQclX623100) : !fir.ref> +! CHECK: %[[V_12:[0-9]+]] = fir.convert %[[V_11]] : (!fir.ref>) -> !fir.ref +! CHECK: %[[V_13:[0-9]+]] = fir.insert_value %[[V_10]], %[[V_12]], [0 : index, 0 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref) -> !fir.array<1xtuple, !fir.ref>>> +! CHECK: %[[V_14:[0-9]+]] = fir.load %[[V_5]] : !fir.ref>>> +! CHECK: %[[V_15:[0-9]+]] = fir.rebox %[[V_14]] : (!fir.class>>) -> !fir.class>> +! CHECK: fir.store %[[V_15]] to %[[V_0]] : !fir.ref>>> +! CHECK: %[[V_16:[0-9]+]] = fir.convert %[[V_0]] : (!fir.ref>>>) -> !fir.ref> +! CHECK: %[[V_17:[0-9]+]] = fir.insert_value %[[V_13]], %[[V_16]], [0 : index, 1 : index] : (!fir.array<1xtuple, !fir.ref>>>, !fir.ref>) -> !fir.array<1xtuple, !fir.ref>>> +! CHECK: fir.store %[[V_17]] to %[[V_9]] : !fir.ref, !fir.ref>>>> namelist/mygroup/b1 write(10, nml=mygroup) end subroutine From 184b976398716627b042576813a740516381f9e0 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Sat, 11 Oct 2025 10:11:15 -0400 Subject: [PATCH 5/5] NFC: to tuning the code a bit to improve readability. --- flang/lib/Lower/IO.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 340406919cdf2..604b13792fc06 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -528,14 +528,14 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter, const auto expr = Fortran::evaluate::AsGenericExpr(s); fir::ExtendedValue exv = converter.genExprAddr(*expr, stmtCtx); mlir::Type type = fir::getBase(exv).getType(); - mlir::Type eleType = type; + bool isClassType = mlir::isa(type); if (mlir::Type baseTy = fir::dyn_cast_ptrOrBoxEleTy(type)) - eleType = baseTy; + type = baseTy; - if (mlir::isa(type)) - boxType = fir::ClassType::get(fir::PointerType::get(eleType)); + if (isClassType) + boxType = fir::ClassType::get(fir::PointerType::get(type)); else - boxType = fir::BoxType::get(fir::PointerType::get(eleType)); + boxType = fir::BoxType::get(fir::PointerType::get(type)); descAddr = builder.createTemporary(loc, boxType); fir::MutableBoxValue box = fir::MutableBoxValue(descAddr, {}, {}); fir::factory::associateMutableBox(builder, loc, box, exv,