[flang] [llvm] [flang] Enhance show_descriptor intrinsic to avoid extra copies and extra descriptor creation (PR #173461)
Eugene Epshteyn via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 30 23:32:29 PST 2025
https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/173461
>From b2d10b48c33fd43d77d01a8a999f6330dfca0467 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 24 Dec 2025 00:16:02 -0500
Subject: [PATCH 1/7] [flang] Avoid descriptor copy in show_descriptor()
Change show_descriptor() lowering to avoid fir.load, which causes
descriptor copy. Also, if non-descriptor entity is passed to
show_descriptor() treat is as null.
---
flang-rt/lib/runtime/extensions.cpp | 2 +-
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 18 ++++++++++++++----
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/flang-rt/lib/runtime/extensions.cpp b/flang-rt/lib/runtime/extensions.cpp
index 100046fc7bbf7..675d46b078288 100644
--- a/flang-rt/lib/runtime/extensions.cpp
+++ b/flang-rt/lib/runtime/extensions.cpp
@@ -471,7 +471,7 @@ void RTNAME(ShowDescriptor)(const Fortran::runtime::Descriptor *descr) {
if (descr) {
descr->Dump(stderr, /*dumpRawType=*/false);
} else {
- std::fprintf(stderr, "NULL\n");
+ std::fprintf(stderr, "NULL or not a descriptor\n");
}
}
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 75a74eeb18417..77b0e9d2efaeb 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -729,7 +729,7 @@ static constexpr IntrinsicHandler handlers[]{
{"shiftr", &I::genShift<mlir::arith::ShRUIOp>},
{"show_descriptor",
&I::genShowDescriptor,
- {{{"d", asBox}}},
+ {{{"d", asInquired}}},
/*isElemental=*/false},
{"sign", &I::genSign},
{"signal",
@@ -7893,9 +7893,19 @@ void IntrinsicLibrary::genShowDescriptor(
assert(args.size() == 1 && "expected single argument for show_descriptor");
const mlir::Value descriptor = fir::getBase(args[0]);
- assert(fir::isa_box_type(descriptor.getType()) &&
- "argument must have been lowered to box type");
- fir::runtime::genShowDescriptor(builder, loc, descriptor);
+ // If it's already a reference to a box, pass it directly.
+ if (fir::isa_ref_type(descriptor.getType()) &&
+ fir::isa_box_type(fir::unwrapRefType(descriptor.getType()))) {
+ fir::runtime::genShowDescriptor(builder, loc, descriptor);
+ return;
+ }
+
+ assert(!fir::isa_box_type(descriptor.getType()) &&
+ "argument must be a reference to a box type");
+
+ // If descriptor is not a box type (and not ref<box>), pass null.
+ mlir::Value nullValue = builder.createNullConstant(loc, fir::BoxType::get(builder.getNoneType()));
+ fir::runtime::genShowDescriptor(builder, loc, nullValue);
}
// SIGNAL
>From 2ddb3c34c724ae5f7274f9ed3bfbbf4e70c12c43 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 24 Dec 2025 01:08:04 -0500
Subject: [PATCH 2/7] Handle case of fir.box in a register that needs to be
spilled to the stack.
---
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 77b0e9d2efaeb..495ae875ab167 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -7900,12 +7900,16 @@ void IntrinsicLibrary::genShowDescriptor(
return;
}
- assert(!fir::isa_box_type(descriptor.getType()) &&
- "argument must be a reference to a box type");
-
- // If descriptor is not a box type (and not ref<box>), pass null.
- mlir::Value nullValue = builder.createNullConstant(loc, fir::BoxType::get(builder.getNoneType()));
- fir::runtime::genShowDescriptor(builder, loc, nullValue);
+ mlir::Value descrAddr = nullptr;
+ if (fir::isa_box_type(descriptor.getType())) {
+ // Spill it to the stack
+ descrAddr = builder.createTemporary(loc, descriptor.getType());
+ builder.createStoreWithConvert(loc, descriptor, descrAddr);
+ } else {
+ // If descriptor is not a box type (and not ref<box>), pass null.
+ descrAddr = builder.createNullConstant(loc, fir::BoxType::get(builder.getNoneType()));
+ }
+ fir::runtime::genShowDescriptor(builder, loc, descrAddr);
}
// SIGNAL
>From 1189c7f80034e20f649720268535db42b8e5862d Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 24 Dec 2025 01:40:46 -0500
Subject: [PATCH 3/7] Updated show_descriptor.f90 LIT test to the new
show_descriptor() implementation
---
.../test/Lower/Intrinsics/show_descriptor.f90 | 84 ++++++-------------
1 file changed, 25 insertions(+), 59 deletions(-)
diff --git a/flang/test/Lower/Intrinsics/show_descriptor.f90 b/flang/test/Lower/Intrinsics/show_descriptor.f90
index a0b8d3eb4348f..d4a5c635b047e 100644
--- a/flang/test/Lower/Intrinsics/show_descriptor.f90
+++ b/flang/test/Lower/Intrinsics/show_descriptor.f90
@@ -10,8 +10,7 @@ subroutine test_int
integer,allocatable :: a(:)
n = 5
allocate(a(n))
-! CHECK: %[[C3:.*]] = arith.constant 3 : index
-! CHECK: %[[C1:.*]] = arith.constant 1 : index
+! CHECK: %[[C0_I64:.*]] = arith.constant 0 : i64
! CHECK: %[[C5:.*]] = arith.constant 5 : i32
! CHECK: %[[C0:.*]] = arith.constant 0 : index
! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
@@ -34,20 +33,11 @@ subroutine test_int
! CHECK: %[[SHAPE_1:.*]] = fir.shape %[[SELECT_0]] : (index) -> !fir.shape<1>
! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[ALLOCMEM_0]](%[[SHAPE_1]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
! CHECK: fir.store %[[EMBOX_1]] to %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
-! CHECK: %[[LOAD_1:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[LOAD_1]]) fastmath<contract> : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[DECLARE_0]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> ()
call show_descriptor(a(1:3))
-! CHECK: %[[LOAD_2:.*]] = fir.load %[[DECLARE_0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
-! CHECK: %[[SHAPE_2:.*]] = fir.shape %[[C3]] : (index) -> !fir.shape<1>
-! CHECK: %[[BOX_ADDR_0:.*]] = fir.box_addr %[[LOAD_2]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
-! CHECK: %[[CONSTANT_4:.*]] = arith.constant 0 : index
-! CHECK: %[[BOX_DIMS_0:.*]]:3 = fir.box_dims %[[LOAD_2]], %[[CONSTANT_4]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index)
-! CHECK: %[[SHAPE_SHIFT_0:.*]] = fir.shape_shift %[[BOX_DIMS_0]]#0, %[[BOX_DIMS_0]]#1 : (index, index) -> !fir.shapeshift<1>
-! CHECK: %[[ARRAY_COOR_0:.*]] = fir.array_coor %[[BOX_ADDR_0]](%[[SHAPE_SHIFT_0]]) %[[C1]] : (!fir.heap<!fir.array<?xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32>
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[ARRAY_COOR_0]] : (!fir.ref<i32>) -> !fir.ref<!fir.array<3xi32>>
-! CHECK: %[[EMBOX_2:.*]] = fir.embox %[[CONVERT_1]](%[[SHAPE_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_2]]) fastmath<contract> : (!fir.box<!fir.array<3xi32>>) -> ()
+! CHECK: %[[ZERO_BITS_1:.*]] = fir.zero_bits !fir.box<none>
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_1]]) fastmath<contract> : (!fir.box<none>) -> ()
deallocate(a)
end subroutine test_int
@@ -56,23 +46,15 @@ subroutine test_char
implicit none
character(len=9) :: c = 'Hey buddy'
call show_descriptor(c)
-! CHECK: %[[C3:.*]] = arith.constant 3 : index
-! CHECK: %[[C1:.*]] = arith.constant 1 : index
! CHECK: %[[C9:.*]] = arith.constant 9 : index
! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[ADDRESS_OF_0:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_charEc) : !fir.ref<!fir.char<1,9>>
! CHECK: %[[DECLARE_0:.*]] = fir.declare %[[ADDRESS_OF_0]] typeparams %[[C9]] {uniq_name = "_QMtest_show_descriptorFtest_charEc"} : (!fir.ref<!fir.char<1,9>>, index) -> !fir.ref<!fir.char<1,9>>
-! CHECK: %[[EMBOX_0:.*]] = fir.embox %[[DECLARE_0]] : (!fir.ref<!fir.char<1,9>>) -> !fir.box<!fir.char<1,9>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_0]]) fastmath<contract> : (!fir.box<!fir.char<1,9>>) -> ()
+! CHECK: %[[ZERO_BITS_2:.*]] = fir.zero_bits !fir.box<none>
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_2]]) fastmath<contract> : (!fir.box<none>) -> ()
call show_descriptor(c(1:3))
-! CHECK: %[[C1_0:.*]] = arith.constant 1 : index
-! CHECK: %[[SUBI_0:.*]] = arith.subi %[[C1]], %[[C1_0]] : index
-! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_0]] : (!fir.ref<!fir.char<1,9>>) -> !fir.ref<!fir.array<9x!fir.char<1>>>
-! CHECK: %[[COORDINATE_OF_0:.*]] = fir.coordinate_of %[[CONVERT_0]], %[[SUBI_0]] : (!fir.ref<!fir.array<9x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
-! CHECK: %[[CONVERT_1:.*]] = fir.convert %[[COORDINATE_OF_0]] : (!fir.ref<!fir.char<1>>) -> !fir.ref<!fir.char<1,3>>
-! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[CONVERT_1]] : (!fir.ref<!fir.char<1,3>>) -> !fir.box<!fir.char<1,3>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_1]]) fastmath<contract> : (!fir.box<!fir.char<1,3>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_2]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
end subroutine test_char
@@ -103,20 +85,17 @@ subroutine test_logical
call show_descriptor(l2)
pla2 => la2
! CHECK: %[[DECLARE_3:.*]] = fir.declare %[[ALLOCA_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtest_show_descriptorFtest_logicalEpla2"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>>
-! CHECK: %[[EMBOX_1:.*]] = fir.embox %[[DECLARE_0]] : (!fir.ref<!fir.logical<1>>) -> !fir.box<!fir.logical<1>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_1]]) fastmath<contract> : (!fir.box<!fir.logical<1>>) -> ()
-! CHECK: %[[EMBOX_2:.*]] = fir.embox %[[DECLARE_1]] : (!fir.ref<!fir.logical<2>>) -> !fir.box<!fir.logical<2>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_2]]) fastmath<contract> : (!fir.box<!fir.logical<2>>) -> ()
+! CHECK: %[[ZERO_BITS_3:.*]] = fir.zero_bits !fir.box<none>
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_3]]) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_3]]) fastmath<contract> : (!fir.box<none>) -> ()
call show_descriptor(la2)
call show_descriptor(pla2)
! CHECK: %[[CONVERT_0:.*]] = fir.convert %[[DECLARE_2]] : (!fir.ref<!fir.array<2x!fir.logical<2>>>) -> !fir.ref<!fir.array<?x!fir.logical<2>>>
! CHECK: %[[EMBOX_3:.*]] = fir.embox %[[CONVERT_0]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<?x!fir.logical<2>>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>
! CHECK: fir.store %[[EMBOX_3]] to %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>>
-! CHECK: %[[EMBOX_4:.*]] = fir.embox %[[DECLARE_2]](%[[SHAPE_0]]) : (!fir.ref<!fir.array<2x!fir.logical<2>>>, !fir.shape<1>) -> !fir.box<!fir.array<2x!fir.logical<2>>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_4]]) fastmath<contract> : (!fir.box<!fir.array<2x!fir.logical<2>>>) -> ()
-! CHECK: %[[LOAD_0:.*]] = fir.load %[[DECLARE_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[LOAD_0]]) fastmath<contract> : (!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_3]]) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[DECLARE_3]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.logical<2>>>>>) -> ()
! CHECK: return
end subroutine test_logical
@@ -130,6 +109,7 @@ subroutine test_real
! CHECK: %[[C1:.*]] = arith.constant 1 : index
! CHECK: %[[C4:.*]] = arith.constant 4 : index
! CHECK: %[[C3:.*]] = arith.constant 3 : index
+! CHECK: %[[ALLOCA_BOX:.*]] = fir.alloca !fir.box<!fir.array<2xf64>>
! CHECK: %[[DUMMY_SCOPE_2:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[ADDRESS_OF_4:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_realEhalf) : !fir.ref<f32>
! CHECK: %[[DECLARE_5:.*]] = fir.declare %[[ADDRESS_OF_4]] {uniq_name = "_QMtest_show_descriptorFtest_realEhalf"} : (!fir.ref<f32>) -> !fir.ref<f32>
@@ -139,22 +119,21 @@ subroutine test_real
! CHECK: %[[ADDRESS_OF_6:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_realEw) : !fir.ref<!fir.array<4xf64>>
! CHECK: %[[SHAPE_3:.*]] = fir.shape %[[C4]] : (index) -> !fir.shape<1>
! CHECK: %[[DECLARE_7:.*]] = fir.declare %[[ADDRESS_OF_6]](%[[SHAPE_3]]) {uniq_name = "_QMtest_show_descriptorFtest_realEw"} : (!fir.ref<!fir.array<4xf64>>, !fir.shape<1>) -> !fir.ref<!fir.array<4xf64>>
+! CHECK: %[[ZERO_BITS_4:.*]] = fir.zero_bits !fir.box<none>
call show_descriptor(half)
call show_descriptor(row)
call show_descriptor(w)
call show_descriptor(w(1:4:2))
-! CHECK: %[[EMBOX_7:.*]] = fir.embox %[[DECLARE_5]] : (!fir.ref<f32>) -> !fir.box<f32>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_7]]) fastmath<contract> : (!fir.box<f32>) -> ()
-! CHECK: %[[EMBOX_8:.*]] = fir.embox %[[DECLARE_6]](%[[SHAPE_2]]) : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xf32>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_8]]) fastmath<contract> : (!fir.box<!fir.array<3xf32>>) -> ()
-! CHECK: %[[EMBOX_9:.*]] = fir.embox %[[DECLARE_7]](%[[SHAPE_3]]) : (!fir.ref<!fir.array<4xf64>>, !fir.shape<1>) -> !fir.box<!fir.array<4xf64>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_9]]) fastmath<contract> : (!fir.box<!fir.array<4xf64>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_4]]) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_4]]) fastmath<contract> : (!fir.box<none>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_4]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: %[[SHAPE_4:.*]] = fir.shape %[[C2]] : (index) -> !fir.shape<1>
! CHECK: %[[UNDEFINED_0:.*]] = fir.undefined index
! CHECK: %[[SLICE_0:.*]] = fir.slice %[[C1]], %[[C4]], %[[C2]] : (index, index, index) -> !fir.slice<1>
! CHECK: %[[EMBOX_10:.*]] = fir.embox %[[DECLARE_7]](%[[SHAPE_3]]) {{\[}}%[[SLICE_0]]] : (!fir.ref<!fir.array<4xf64>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<2xf64>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_10]]) fastmath<contract> : (!fir.box<!fir.array<2xf64>>) -> ()
+! CHECK: fir.store %[[EMBOX_10]] to %[[ALLOCA_BOX]] : !fir.ref<!fir.box<!fir.array<2xf64>>>
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ALLOCA_BOX]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.array<2xf64>>>) -> ()
! CHECK: return
end subroutine test_real
@@ -166,11 +145,7 @@ subroutine test_complex
complex :: c1 = hr
complex :: c2 = hi
complex :: a2(2) = (/ hr, hi /)
-! CHECK: %[[CST_0:.*]] = arith.constant 0.000000e+00 : f32
-! CHECK: %[[CST_1:.*]] = arith.constant 5.000000e-01 : f32
! CHECK: %[[C2:.*]] = arith.constant 2 : index
-! CHECK: %[[ALLOCA_1:.*]] = fir.alloca complex<f32>
-! CHECK: %[[ALLOCA_2:.*]] = fir.alloca complex<f32>
! CHECK: %[[DUMMY_SCOPE_3:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[ADDRESS_OF_7:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEa2) : !fir.ref<!fir.array<2xcomplex<f32>>>
! CHECK: %[[SHAPE_5:.*]] = fir.shape %[[C2]] : (index) -> !fir.shape<1>
@@ -183,25 +158,16 @@ subroutine test_complex
! CHECK: %[[DECLARE_11:.*]] = fir.declare %[[ADDRESS_OF_10]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMtest_show_descriptorFtest_complexEChi"} : (!fir.ref<complex<f32>>) -> !fir.ref<complex<f32>>
! CHECK: %[[ADDRESS_OF_11:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_complexEChr) : !fir.ref<complex<f32>>
! CHECK: %[[DECLARE_12:.*]] = fir.declare %[[ADDRESS_OF_11]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QMtest_show_descriptorFtest_complexEChr"} : (!fir.ref<complex<f32>>) -> !fir.ref<complex<f32>>
-! CHECK: %[[UNDEFINED_1:.*]] = fir.undefined complex<f32>
-! CHECK: %[[INSERT_VALUE_0:.*]] = fir.insert_value %[[UNDEFINED_1]], %[[CST_1]], [0 : index] : (complex<f32>, f32) -> complex<f32>
-! CHECK: %[[INSERT_VALUE_1:.*]] = fir.insert_value %[[INSERT_VALUE_0]], %[[CST_0]], [1 : index] : (complex<f32>, f32) -> complex<f32>
-! CHECK: fir.store %[[INSERT_VALUE_1]] to %[[ALLOCA_2]] : !fir.ref<complex<f32>>
+! CHECK: %[[ZERO_BITS_5:.*]] = fir.zero_bits !fir.box<none>
call show_descriptor(hr)
-! CHECK: %[[EMBOX_11:.*]] = fir.embox %[[ALLOCA_2]] : (!fir.ref<complex<f32>>) -> !fir.box<complex<f32>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_11]]) fastmath<contract> : (!fir.box<complex<f32>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_5]]) fastmath<contract> : (!fir.box<none>) -> ()
call show_descriptor(hi)
-! CHECK: %[[INSERT_VALUE_2:.*]] = fir.insert_value %[[UNDEFINED_1]], %[[CST_0]], [0 : index] : (complex<f32>, f32) -> complex<f32>
-! CHECK: %[[INSERT_VALUE_3:.*]] = fir.insert_value %[[INSERT_VALUE_2]], %[[CST_1]], [1 : index] : (complex<f32>, f32) -> complex<f32>
-! CHECK: fir.store %[[INSERT_VALUE_3]] to %[[ALLOCA_1]] : !fir.ref<complex<f32>>
-! CHECK: %[[EMBOX_12:.*]] = fir.embox %[[ALLOCA_1]] : (!fir.ref<complex<f32>>) -> !fir.box<complex<f32>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_12]]) fastmath<contract> : (!fir.box<complex<f32>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_5]]) fastmath<contract> : (!fir.box<none>) -> ()
call show_descriptor(a2)
-! CHECK: %[[EMBOX_13:.*]] = fir.embox %[[DECLARE_8]](%[[SHAPE_5]]) : (!fir.ref<!fir.array<2xcomplex<f32>>>, !fir.shape<1>) -> !fir.box<!fir.array<2xcomplex<f32>>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_13]]) fastmath<contract> : (!fir.box<!fir.array<2xcomplex<f32>>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_5]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
end subroutine test_complex
@@ -232,10 +198,10 @@ subroutine test_derived
! CHECK: %[[DECLARE_17:.*]] = fir.declare %[[ADDRESS_OF_16]] typeparams %[[C2]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.t2"} : (!fir.ref<!fir.char<1,2>>, index) -> !fir.ref<!fir.char<1,2>>
! CHECK: %[[ADDRESS_OF_17:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedEvt2) : !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>
! CHECK: %[[DECLARE_18:.*]] = fir.declare %[[ADDRESS_OF_17]] {uniq_name = "_QMtest_show_descriptorFtest_derivedEvt2"} : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>
+! CHECK: %[[ZERO_BITS_6:.*]] = fir.zero_bits !fir.box<none>
call show_descriptor(vt2)
-! CHECK: %[[EMBOX_16:.*]] = fir.embox %[[DECLARE_18]] : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> !fir.box<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>
-! CHECK: fir.call @_FortranAShowDescriptor(%[[EMBOX_16]]) fastmath<contract> : (!fir.box<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> ()
+! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_6]]) fastmath<contract> : (!fir.box<none>) -> ()
! CHECK: return
end subroutine test_derived
end module test_show_descriptor
>From f47a8f2c60c6e8ff6bc783e73ef0b525ccba90c6 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 24 Dec 2025 01:41:41 -0500
Subject: [PATCH 4/7] clang-format
---
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 495ae875ab167..e73212ab25203 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -7907,7 +7907,8 @@ void IntrinsicLibrary::genShowDescriptor(
builder.createStoreWithConvert(loc, descriptor, descrAddr);
} else {
// If descriptor is not a box type (and not ref<box>), pass null.
- descrAddr = builder.createNullConstant(loc, fir::BoxType::get(builder.getNoneType()));
+ descrAddr = builder.createNullConstant(
+ loc, fir::BoxType::get(builder.getNoneType()));
}
fir::runtime::genShowDescriptor(builder, loc, descrAddr);
}
>From fa1edea2d3545df930eb21ee7161c30c7ace1642 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Wed, 24 Dec 2025 13:31:21 -0500
Subject: [PATCH 5/7] Apply suggestion from @vzakhari
Comment change
Co-authored-by: Slava Zakharin <szakharin at nvidia.com>
---
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index e73212ab25203..efd78ae796d26 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -7906,7 +7906,7 @@ void IntrinsicLibrary::genShowDescriptor(
descrAddr = builder.createTemporary(loc, descriptor.getType());
builder.createStoreWithConvert(loc, descriptor, descrAddr);
} else {
- // If descriptor is not a box type (and not ref<box>), pass null.
+ // If argument is not a box type (and not ref<box>), pass null.
descrAddr = builder.createNullConstant(
loc, fir::BoxType::get(builder.getNoneType()));
}
>From f05093e6ab1f78906ba90c1ceccde6970baa8f58 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Tue, 30 Dec 2025 00:49:52 -0500
Subject: [PATCH 6/7] show-descriptor.f90: added polymorphic tests
---
.../test/Lower/Intrinsics/show_descriptor.f90 | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/flang/test/Lower/Intrinsics/show_descriptor.f90 b/flang/test/Lower/Intrinsics/show_descriptor.f90
index d4a5c635b047e..595ca0bc4181b 100644
--- a/flang/test/Lower/Intrinsics/show_descriptor.f90
+++ b/flang/test/Lower/Intrinsics/show_descriptor.f90
@@ -182,6 +182,12 @@ subroutine test_derived
integer :: c
end type t2
type(t2) :: vt2 = t2(7,5,3)
+ class(t1), allocatable :: c_t1
+ class(*), allocatable :: c_unlimited
+ allocate(t2 :: c_t1)
+ c_t1 = vt2
+ allocate(c_unlimited, source=vt2)
+
! CHECK: %[[C0:.*]] = arith.constant 0 : index
! CHECK: %[[C2:.*]] = arith.constant 2 : index
! CHECK: %[[C1:.*]] = arith.constant 1 : index
@@ -196,12 +202,28 @@ subroutine test_derived
! CHECK: %[[DECLARE_16:.*]] = fir.declare %[[ADDRESS_OF_15]] typeparams %[[C1]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.c"} : (!fir.ref<!fir.char<1>>, index) -> !fir.ref<!fir.char<1>>
! CHECK: %[[ADDRESS_OF_16:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedE.n.t2) : !fir.ref<!fir.char<1,2>>
! CHECK: %[[DECLARE_17:.*]] = fir.declare %[[ADDRESS_OF_16]] typeparams %[[C2]] {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMtest_show_descriptorFtest_derivedE.n.t2"} : (!fir.ref<!fir.char<1,2>>, index) -> !fir.ref<!fir.char<1,2>>
+! CHECK: %[[ALLOCA_CT1:.*]] = fir.alloca !fir.class<!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>> {bindc_name = "c_t1", uniq_name = "_QMtest_show_descriptorFtest_derivedEc_t1"}
+! CHECK: %[[ZERO_BITS_CT1:.*]] = fir.zero_bits !fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>
+! CHECK: %[[EMBOX_CT1:.*]] = fir.embox %[[ZERO_BITS_CT1]] : (!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>) -> !fir.class<!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>>
+! CHECK: fir.store %[[EMBOX_CT1]] to %[[ALLOCA_CT1]] : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>>>
+! CHECK: %[[DECLARE_CT1:.*]] = fir.declare %[[ALLOCA_CT1]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMtest_show_descriptorFtest_derivedEc_t1"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.class<!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>>>
+! CHECK: %[[ALLOCA_CU:.*]] = fir.alloca !fir.class<!fir.heap<none>> {bindc_name = "c_unlimited", uniq_name = "_QMtest_show_descriptorFtest_derivedEc_unlimited"}
+! CHECK: %[[ZERO_BITS_CU:.*]] = fir.zero_bits !fir.heap<none>
+! CHECK: %[[EMBOX_CU:.*]] = fir.embox %[[ZERO_BITS_CU]] : (!fir.heap<none>) -> !fir.class<!fir.heap<none>>
+! CHECK: fir.store %[[EMBOX_CU]] to %[[ALLOCA_CU]] : !fir.ref<!fir.class<!fir.heap<none>>>
+! CHECK: %[[DECLARE_CU:.*]] = fir.declare %[[ALLOCA_CU]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMtest_show_descriptorFtest_derivedEc_unlimited"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[ADDRESS_OF_17:.*]] = fir.address_of(@_QMtest_show_descriptorFtest_derivedEvt2) : !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>
! CHECK: %[[DECLARE_18:.*]] = fir.declare %[[ADDRESS_OF_17]] {uniq_name = "_QMtest_show_descriptorFtest_derivedEvt2"} : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>) -> !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derivedTt2{t1:!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>,c:i32}>>
! CHECK: %[[ZERO_BITS_6:.*]] = fir.zero_bits !fir.box<none>
call show_descriptor(vt2)
! CHECK: fir.call @_FortranAShowDescriptor(%[[ZERO_BITS_6]]) fastmath<contract> : (!fir.box<none>) -> ()
+
+ call show_descriptor(c_t1)
+! CHECK: fir.call @_FortranAShowDescriptor(%[[DECLARE_CT1]]) fastmath<contract> : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMtest_show_descriptorFtest_derivedTt1{a:i32,b:i32}>>>>) -> ()
+
+ call show_descriptor(c_unlimited)
+! CHECK: fir.call @_FortranAShowDescriptor(%[[DECLARE_CU]]) fastmath<contract> : (!fir.ref<!fir.class<!fir.heap<none>>>) -> ()
! CHECK: return
end subroutine test_derived
end module test_show_descriptor
>From 8cddda3df3308d9ef93df9360a2755903d4b02cb Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Tue, 30 Dec 2025 01:07:22 -0500
Subject: [PATCH 7/7] show-descriptor.f90: add a test for descriptor as derived
type component
---
flang/test/Lower/Intrinsics/show_descriptor.f90 | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/flang/test/Lower/Intrinsics/show_descriptor.f90 b/flang/test/Lower/Intrinsics/show_descriptor.f90
index 595ca0bc4181b..c0679c411fa72 100644
--- a/flang/test/Lower/Intrinsics/show_descriptor.f90
+++ b/flang/test/Lower/Intrinsics/show_descriptor.f90
@@ -226,4 +226,21 @@ subroutine test_derived
! CHECK: fir.call @_FortranAShowDescriptor(%[[DECLARE_CU]]) fastmath<contract> : (!fir.ref<!fir.class<!fir.heap<none>>>) -> ()
! CHECK: return
end subroutine test_derived
+
+subroutine test_derived_member
+! CHECK-LABEL: func.func @_QMtest_show_descriptorPtest_derived_member() {
+ implicit none
+ type :: t3
+ integer, allocatable :: a(:)
+ end type t3
+ type(t3) :: vt3
+! CHECK: %[[VT3:.*]] = fir.alloca !fir.type<_QMtest_show_descriptorFtest_derived_memberTt3{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>
+! CHECK: %[[VT3_DECL:.*]] = fir.declare %[[VT3]] {uniq_name = "_QMtest_show_descriptorFtest_derived_memberEvt3"} : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derived_memberTt3{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.type<_QMtest_show_descriptorFtest_derived_memberTt3{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+ allocate(vt3%a(5))
+! CHECK: %[[A_FIELD:.*]] = fir.field_index a, !fir.type<_QMtest_show_descriptorFtest_derived_memberTt3{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>
+! CHECK: %[[A_COORD:.*]] = fir.coordinate_of %[[VT3_DECL]], a : (!fir.ref<!fir.type<_QMtest_show_descriptorFtest_derived_memberTt3{a:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ call show_descriptor(vt3%a)
+! CHECK: fir.call @_FortranAShowDescriptor(%[[A_COORD]]) fastmath<contract> : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> ()
+ deallocate(vt3%a)
+end subroutine test_derived_member
end module test_show_descriptor
More information about the llvm-commits
mailing list