Skip to content

[flang] Do not instantiate runtime info globals in functions #80447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions flang/include/flang/Lower/PFTBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ struct Variable {
return *std::get<Nominal>(var).symbol;
}

/// Is this variable a compiler generated global to describe derived types?
bool isRuntimeTypeInfoData() const;

/// Return the aggregate store.
const AggregateStore &getAggregateStore() const {
assert(isAggregateStore());
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4358,7 +4358,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
if (scp->kind() == Fortran::semantics::Scope::Kind::Module)
for (const auto &var : Fortran::lower::pft::getScopeVariableList(
*scp, scopeVariableListMap))
instantiateVar(var, storeMap);
if (!var.isRuntimeTypeInfoData())
instantiateVar(var, storeMap);

// Map function equivalences and variables.
mlir::Value primaryFuncResultStorage;
Expand Down
14 changes: 1 addition & 13 deletions flang/lib/Lower/ConvertVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,6 @@ static bool isConstant(const Fortran::semantics::Symbol &sym) {
sym.test(Fortran::semantics::Symbol::Flag::ReadOnly);
}

/// Is this a compiler generated symbol to describe derived types ?
static bool isRuntimeTypeInfoData(const Fortran::semantics::Symbol &sym) {
// So far, use flags to detect if this symbol were generated during
// semantics::BuildRuntimeDerivedTypeTables(). Scope cannot be used since the
// symbols are injected in the user scopes defining the described derived
// types. A robustness improvement for this test could be to get hands on the
// semantics::RuntimeDerivedTypeTables and to check if the symbol names
// belongs to this structure.
return sym.test(Fortran::semantics::Symbol::Flag::CompilerCreated) &&
sym.test(Fortran::semantics::Symbol::Flag::ReadOnly);
}

static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var,
llvm::StringRef globalName,
Expand Down Expand Up @@ -626,7 +614,7 @@ getLinkageAttribute(fir::FirOpBuilder &builder,
// unit. It desired to avoid having to link against module that only define a
// type. Therefore the runtime type info is generated everywhere it is needed
// with `linkonce_odr` LLVM linkage.
if (var.hasSymbol() && isRuntimeTypeInfoData(var.getSymbol()))
if (var.isRuntimeTypeInfoData())
return builder.createLinkOnceODRLinkage();
if (var.isModuleOrSubmoduleVariable())
return {}; // external linkage
Expand Down
21 changes: 21 additions & 0 deletions flang/lib/Lower/PFTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,27 @@ Fortran::lower::pft::BlockDataUnit::BlockDataUnit(
std::get<parser::Statement<parser::EndBlockDataStmt>>(bd.t).source)} {
}

//===----------------------------------------------------------------------===//
// Variable implementation
//===----------------------------------------------------------------------===//

bool Fortran::lower::pft::Variable::isRuntimeTypeInfoData() const {
// So far, use flags to detect if this symbol were generated during
// semantics::BuildRuntimeDerivedTypeTables(). Scope cannot be used since the
// symbols are injected in the user scopes defining the described derived
// types. A robustness improvement for this test could be to get hands on the
// semantics::RuntimeDerivedTypeTables and to check if the symbol names
// belongs to this structure.
using Flags = Fortran::semantics::Symbol::Flag;
const auto *nominal = std::get_if<Nominal>(&var);
return nominal && nominal->symbol->test(Flags::CompilerCreated) &&
nominal->symbol->test(Flags::ReadOnly);
}

//===----------------------------------------------------------------------===//
// API implementation
//===----------------------------------------------------------------------===//

std::unique_ptr<lower::pft::Program>
Fortran::lower::createPFT(const parser::Program &root,
const semantics::SemanticsContext &semanticsContext) {
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenACC/acc-bounds.f90
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ subroutine acc_multi_strides(a)
! CHECK: %[[BOX_DIMS2:.*]]:3 = fir.box_dims %[[DECL_ARG0]]#0, %c2{{.*}} : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
! CHECK: %[[BOUNDS2:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%[[BOX_DIMS2]]#1 : index) stride(%[[STRIDE2]] : index) startIdx(%{{.*}} : index) {strideInBytes = true}
! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_ARG0]]#0 : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
! 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"}
! 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"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this!

! CHECK: acc.kernels dataOperands(%[[PRESENT]] : !fir.ref<!fir.array<?x?x?xf32>>) {

subroutine acc_optional_data(a)
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Lower/allocatable-polymorphic.f90
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ subroutine test_allocatable()
! CHECK: %[[TYPE_DESC_ADDR:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}>
! 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>>
! CHECK: %[[TYPE_NONE:.*]] = fir.convert %[[TYPE_DESC_ADDR]] : (!fir.tdesc<!fir.type<_QMpolyTp1{a:i32,b:i32}>>) -> !fir.ref<none>
! 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
! 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

! CHECK: %[[TYPE_DESC_ADDR:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}>
! 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>>
Expand Down Expand Up @@ -421,7 +421,7 @@ subroutine test_type_with_polymorphic_pointer_component()

! CHECK-LABEL: func.func @_QMpolyPtest_type_with_polymorphic_pointer_component()
! 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"}
! 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}>>>}>>>>)
! 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}>>>}>>>>)
! 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>>
! CHECK: fir.call @_FortranAPointerAllocate(%[[TYPE_PTR_CONV]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! 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}>>>}>>>>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/nullify-polymorphic.f90
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ program test

! CHECK-LABEL: func.func @_QMpolyPtest_nullify()
! CHECK: %[[C_DESC:.*]] = fir.alloca !fir.class<!fir.ptr<!fir.type<_QMpolyTp1{a:i32,b:i32}>>> {bindc_name = "c", uniq_name = "_QMpolyFtest_nullifyEc"}
! 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}>>>>)
! 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}>>>>)
! CHECK: %{{.*}} = fir.call @_FortranAPointerAllocate(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
! CHECK: %[[DECLARED_TYPE_DESC:.*]] = fir.type_desc !fir.type<_QMpolyTp1{a:i32,b:i32}>
! 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>>
Expand Down