Skip to content

Commit 0a45d17

Browse files
authored
[flang] Do not instantiate runtime info globals in functions (#80447)
Runtime globals are compiler generated globals injected in user scopes. They are never referred to directly in lowering code, we only need th fur.global for them. Yet lowering was creating hlfir.declare for them in module procedures. In modern fortran apps, this blows up the generated IR for nothing (Types with dozens of components, type bound procedures and parents can create in the order of 10 000 runtime info globals to describe them, if there is a 100 module procedure, that is that is a few million operations generated and processed in each pass for nothing).
1 parent 7d2b6f0 commit 0a45d17

File tree

7 files changed

+31
-18
lines changed

7 files changed

+31
-18
lines changed

flang/include/flang/Lower/PFTBuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,9 @@ struct Variable {
463463
return *std::get<Nominal>(var).symbol;
464464
}
465465

466+
/// Is this variable a compiler generated global to describe derived types?
467+
bool isRuntimeTypeInfoData() const;
468+
466469
/// Return the aggregate store.
467470
const AggregateStore &getAggregateStore() const {
468471
assert(isAggregateStore());

flang/lib/Lower/Bridge.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4358,7 +4358,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
43584358
if (scp->kind() == Fortran::semantics::Scope::Kind::Module)
43594359
for (const auto &var : Fortran::lower::pft::getScopeVariableList(
43604360
*scp, scopeVariableListMap))
4361-
instantiateVar(var, storeMap);
4361+
if (!var.isRuntimeTypeInfoData())
4362+
instantiateVar(var, storeMap);
43624363

43634364
// Map function equivalences and variables.
43644365
mlir::Value primaryFuncResultStorage;

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,18 +134,6 @@ static bool isConstant(const Fortran::semantics::Symbol &sym) {
134134
sym.test(Fortran::semantics::Symbol::Flag::ReadOnly);
135135
}
136136

137-
/// Is this a compiler generated symbol to describe derived types ?
138-
static bool isRuntimeTypeInfoData(const Fortran::semantics::Symbol &sym) {
139-
// So far, use flags to detect if this symbol were generated during
140-
// semantics::BuildRuntimeDerivedTypeTables(). Scope cannot be used since the
141-
// symbols are injected in the user scopes defining the described derived
142-
// types. A robustness improvement for this test could be to get hands on the
143-
// semantics::RuntimeDerivedTypeTables and to check if the symbol names
144-
// belongs to this structure.
145-
return sym.test(Fortran::semantics::Symbol::Flag::CompilerCreated) &&
146-
sym.test(Fortran::semantics::Symbol::Flag::ReadOnly);
147-
}
148-
149137
static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
150138
const Fortran::lower::pft::Variable &var,
151139
llvm::StringRef globalName,
@@ -626,7 +614,7 @@ getLinkageAttribute(fir::FirOpBuilder &builder,
626614
// unit. It desired to avoid having to link against module that only define a
627615
// type. Therefore the runtime type info is generated everywhere it is needed
628616
// with `linkonce_odr` LLVM linkage.
629-
if (var.hasSymbol() && isRuntimeTypeInfoData(var.getSymbol()))
617+
if (var.isRuntimeTypeInfoData())
630618
return builder.createLinkOnceODRLinkage();
631619
if (var.isModuleOrSubmoduleVariable())
632620
return {}; // external linkage

flang/lib/Lower/PFTBuilder.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,27 @@ Fortran::lower::pft::BlockDataUnit::BlockDataUnit(
18021802
std::get<parser::Statement<parser::EndBlockDataStmt>>(bd.t).source)} {
18031803
}
18041804

1805+
//===----------------------------------------------------------------------===//
1806+
// Variable implementation
1807+
//===----------------------------------------------------------------------===//
1808+
1809+
bool Fortran::lower::pft::Variable::isRuntimeTypeInfoData() const {
1810+
// So far, use flags to detect if this symbol were generated during
1811+
// semantics::BuildRuntimeDerivedTypeTables(). Scope cannot be used since the
1812+
// symbols are injected in the user scopes defining the described derived
1813+
// types. A robustness improvement for this test could be to get hands on the
1814+
// semantics::RuntimeDerivedTypeTables and to check if the symbol names
1815+
// belongs to this structure.
1816+
using Flags = Fortran::semantics::Symbol::Flag;
1817+
const auto *nominal = std::get_if<Nominal>(&var);
1818+
return nominal && nominal->symbol->test(Flags::CompilerCreated) &&
1819+
nominal->symbol->test(Flags::ReadOnly);
1820+
}
1821+
1822+
//===----------------------------------------------------------------------===//
1823+
// API implementation
1824+
//===----------------------------------------------------------------------===//
1825+
18051826
std::unique_ptr<lower::pft::Program>
18061827
Fortran::lower::createPFT(const parser::Program &root,
18071828
const semantics::SemanticsContext &semanticsContext) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ subroutine acc_multi_strides(a)
115115
! CHECK: %[[BOX_DIMS2:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c2{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
116116
! CHECK: %[[BOUNDS2:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS2]]#1 : index) stride(%[[STRIDE2]] : index) startIdx(%{{.*}} : index) {strideInBytes = true}
117117
! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#0 : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
118-
! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?x?x?xf32>>) bounds(%29, %33, %37) -> !fir.ref<!fir.array<?x?x?xf32>> {name = "a"}
118+
! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?x?x?xf32>>) bounds(%[[BOUNDS0]], %[[BOUNDS1]], %[[BOUNDS2]]) -> !fir.ref<!fir.array<?x?x?xf32>> {name = "a"}
119119
! CHECK: acc.kernels dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<?x?x?xf32>>) {
120120

121121
subroutine acc_optional_data(a)

flang/test/Lower/allocatable-polymorphic.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ subroutine test_allocatable()
345345
! CHECK: %[[TYPE_DESC_ADDR:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}>
346346
! CHECK: %[[P_CAST:.*]] = fir.convert %[[P_DECL]]#1 : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
347347
! CHECK: %[[TYPE_NONE:.*]] = fir.convert %[[TYPE_DESC_ADDR]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
348-
! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%[[P_CAST]], %[[TYPE_NONE]], %{{.*}}, %1{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.ref<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
348+
! CHECK: %{{.*}} = fir.call @_FortranAAllocatableDeallocatePolymorphic(%[[P_CAST]], %[[TYPE_NONE]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, !fir.ref<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
349349

350350
! CHECK: %[[TYPE_DESC_ADDR:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}>
351351
! CHECK: %[[C1_CAST:.*]] = fir.convert %[[C1_DECL]]#1 : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
@@ -421,7 +421,7 @@ subroutine test_type_with_polymorphic_pointer_component()
421421

422422
! CHECK-LABEL: func.func @_QMpolyPtest_type_with_polymorphic_pointer_component()
423423
! CHECK: %[[TYPE_PTR:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>> {bindc_name = "a", uniq_name = "_QMpolyFtest_type_with_polymorphic_pointer_componentEa"}
424-
! CHECK: %[[TYPE_PTR_DECL:.*]]:2 = hlfir.declare %39 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_type_with_polymorphic_pointer_componentEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>)
424+
! CHECK: %[[TYPE_PTR_DECL:.*]]:2 = hlfir.declare %[[TYPE_PTR]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_type_with_polymorphic_pointer_componentEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>)
425425
! CHECK: %[[TYPE_PTR_CONV:.*]] = fir.convert %[[TYPE_PTR_DECL]]#1 : (!fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>) -> !fir.ref<!fir.box<none>>
426426
! CHECK: fir.call @_FortranAPointerAllocate(%[[TYPE_PTR_CONV]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
427427
! CHECK: %[[TYPE_PTR_LOAD:.*]] = fir.load %[[TYPE_PTR_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMpolyTwith_alloc{element:!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>}>>>>

flang/test/Lower/nullify-polymorphic.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ program test
4343

4444
! CHECK-LABEL: func.func @_QMpolyPtest_nullify()
4545
! CHECK: %[[C_DESC:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>> {bindc_name = "c", uniq_name = "_QMpolyFtest_nullifyEc"}
46-
! CHECK: %[[C_DESC_DECL:.*]]:2 = hlfir.declare %28 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_nullifyEc"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>)
46+
! CHECK: %[[C_DESC_DECL:.*]]:2 = hlfir.declare %[[C_DESC]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMpolyFtest_nullifyEc"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>)
4747
! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
4848
! CHECK: %[[DECLARED_TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}>
4949
! CHECK: %[[C_DESC_CAST:.*]] = fir.convert %[[C_DESC_DECL]]#1 : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>

0 commit comments

Comments
 (0)