diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h --- a/flang/include/flang/Lower/CallInterface.h +++ b/flang/include/flang/Lower/CallInterface.h @@ -345,6 +345,9 @@ llvm_unreachable("getting host associated type in CallerInterface"); } + /// Set attributes on MLIR function. + void setFuncAttrs(mlir::func::FuncOp) const {} + private: /// Check that the input vector is complete. bool verifyActualInputs() const; @@ -395,6 +398,7 @@ bool hasHostAssociated() const; mlir::Type getHostAssociatedTy() const; mlir::Value getHostAssociatedTuple() const; + void setFuncAttrs(mlir::func::FuncOp) const; private: Fortran::lower::pft::FunctionLikeUnit &funit; diff --git a/flang/include/flang/Lower/HostAssociations.h b/flang/include/flang/Lower/HostAssociations.h --- a/flang/include/flang/Lower/HostAssociations.h +++ b/flang/include/flang/Lower/HostAssociations.h @@ -17,7 +17,8 @@ namespace Fortran { namespace semantics { class Symbol; -} +class Scope; +} // namespace semantics namespace lower { class AbstractConverter; @@ -29,15 +30,17 @@ class HostAssociations { public: /// Returns true iff there are no host associations. - bool empty() const { return symbols.empty(); } + bool empty() const { return tupleSymbols.empty() && globalSymbols.empty(); } + + /// Returns true iff there are host associations that are conveyed through + /// an extra tuple argument. + bool hasTupleAssociations() const { return !tupleSymbols.empty(); } /// Adds a set of Symbols that will be the host associated bindings for this /// host procedure. void addSymbolsToBind( - const llvm::SetVector &s) { - assert(empty() && "symbol set must be initially empty"); - symbols = s; - } + const llvm::SetVector &symbols, + const Fortran::semantics::Scope &hostScope); /// Code gen the FIR for the local bindings for the host associated symbols /// for the host (parent) procedure using `builder`. @@ -52,15 +55,21 @@ /// Is \p symbol host associated ? bool isAssociated(const Fortran::semantics::Symbol &symbol) const { - return symbols.contains(&symbol); + return tupleSymbols.contains(&symbol) || globalSymbols.contains(&symbol); } private: - /// Canonical vector of host associated symbols. - llvm::SetVector symbols; + /// Canonical vector of host associated local symbols. + llvm::SetVector tupleSymbols; + + /// Canonical vector of host associated global symbols. + llvm::SetVector globalSymbols; /// The type of the extra argument to be added to each internal procedure. mlir::Type argType; + + /// Scope of the parent procedure if addSymbolsToBind was called. + const Fortran::semantics::Scope *hostScope; }; } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Lower/PFTBuilder.h b/flang/include/flang/Lower/PFTBuilder.h --- a/flang/include/flang/Lower/PFTBuilder.h +++ b/flang/include/flang/Lower/PFTBuilder.h @@ -651,7 +651,7 @@ void setHostAssociatedSymbols( const llvm::SetVector &symbols) { - hostAssociations.addSymbolsToBind(symbols); + hostAssociations.addSymbolsToBind(symbols, getScope()); } /// Return the host associations, if any, from the parent (host) procedure. @@ -659,7 +659,12 @@ HostAssociations &parentHostAssoc(); /// Return true iff the parent is a procedure and the parent has a non-empty - /// set of host associations. + /// set of host associations that are conveyed through an extra tuple + /// argument. + bool parentHasTupleHostAssoc(); + + /// Return true iff the parent is a procedure and the parent has a non-empty + /// set of host associations for variables. bool parentHasHostAssoc(); /// Return the host associations for this function like unit. The list of host diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h --- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h +++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h @@ -88,10 +88,22 @@ return "fir.host_assoc"; } +/// Attribute to mark an internal procedure. +static constexpr llvm::StringRef getInternalProcedureAttrName() { + return "fir.internal_proc"; +} + /// Does the function, \p func, have a host-associations tuple argument? /// Some internal procedures may have access to host procedure variables. bool hasHostAssociationArgument(mlir::func::FuncOp func); +/// Is the function, \p func an internal procedure ? +/// Some internal procedures may have access to saved host procedure +/// variables even when they do not have a tuple argument. +inline bool isInternalPorcedure(mlir::func::FuncOp func) { + return func->hasAttr(fir::getInternalProcedureAttrName()); +} + /// Tell if \p value is: /// - a function argument that has attribute \p attributeName /// - or, the result of fir.alloca/fir.allocamem op that has attribute \p diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -3212,9 +3212,7 @@ } addSymbol(arg.entity->get(), arg.firArgument); } else { - assert(funit.parentHasHostAssoc()); - funit.parentHostAssoc().internalProcedureBindings(*this, - localSymbols); + assert(funit.parentHasTupleHostAssoc() && "expect tuple argument"); } } }; @@ -3260,6 +3258,10 @@ mapDummiesAndResults(funit, callee); + // Map host associated symbols from parent procedure if any. + if (funit.parentHasHostAssoc()) + funit.parentHostAssoc().internalProcedureBindings(*this, localSymbols); + // Non-primary results of a function with multiple entry points. // These result values share storage with the primary result. llvm::SmallVector deferredFuncResultList; @@ -3302,9 +3304,7 @@ // to the host variable, which must be in the map. const Fortran::semantics::Symbol &ultimate = sym.GetUltimate(); if (funit.parentHostAssoc().isAssociated(ultimate)) { - Fortran::lower::SymbolBox hostBox = lookupSymbol(ultimate); - assert(hostBox && "host association is not in map"); - localSymbols.addSymbol(sym, hostBox.toExtendedValue()); + copySymbolBinding(ultimate, sym); continue; } } diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -426,7 +426,7 @@ } bool Fortran::lower::CalleeInterface::hasHostAssociated() const { - return funit.parentHasHostAssoc(); + return funit.parentHasTupleHostAssoc(); } mlir::Type Fortran::lower::CalleeInterface::getHostAssociatedTy() const { @@ -439,6 +439,13 @@ return converter.hostAssocTupleValue(); } +void Fortran::lower::CalleeInterface::setFuncAttrs( + mlir::func::FuncOp func) const { + if (funit.parentHasHostAssoc()) + func->setAttr(fir::getInternalProcedureAttrName(), + mlir::UnitAttr::get(func->getContext())); +} + //===----------------------------------------------------------------------===// // CallInterface implementation: this part is common to both caller and caller // sides. @@ -484,6 +491,7 @@ for (const auto &placeHolder : llvm::enumerate(inputs)) if (!placeHolder.value().attributes.empty()) func.setArgAttrs(placeHolder.index(), placeHolder.value().attributes); + side().setFuncAttrs(func); } } } diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -13,6 +13,7 @@ #include "flang/Lower/BoxAnalyzer.h" #include "flang/Lower/CallInterface.h" #include "flang/Lower/ConvertType.h" +#include "flang/Lower/ConvertVariable.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Character.h" @@ -480,10 +481,25 @@ return builder.create(loc, ty, tupleArg, offset); } +void Fortran::lower::HostAssociations::addSymbolsToBind( + const llvm::SetVector &symbols, + const Fortran::semantics::Scope &hostScope) { + assert(tupleSymbols.empty() && globalSymbols.empty() && + "must be initially empty"); + this->hostScope = &hostScope; + for (const auto *s : symbols) + if (Fortran::lower::symbolIsGlobal(*s)) + // The ultimate symbol is stored here so that global symbols from the + // host scope can later be searched in this set. + globalSymbols.insert(&s->GetUltimate()); + else + tupleSymbols.insert(s); +} + void Fortran::lower::HostAssociations::hostProcedureBindings( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symMap) { - if (symbols.empty()) + if (tupleSymbols.empty()) return; // Create the tuple variable. @@ -493,8 +509,8 @@ auto hostTuple = builder.create(loc, tupTy); mlir::IntegerType offTy = builder.getIntegerType(32); - // Walk the list of symbols and update the pointers in the tuple. - for (auto s : llvm::enumerate(symbols)) { + // Walk the list of tupleSymbols and update the pointers in the tuple. + for (auto s : llvm::enumerate(tupleSymbols)) { auto indexInTuple = s.index(); mlir::Value off = builder.createIntegerConstant(loc, offTy, indexInTuple); mlir::Type varTy = tupTy.getType(indexInTuple); @@ -510,7 +526,20 @@ void Fortran::lower::HostAssociations::internalProcedureBindings( Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symMap) { - if (symbols.empty()) + if (!globalSymbols.empty()) { + assert(hostScope && "host scope must have been set"); + Fortran::lower::AggregateStoreMap storeMap; + // The host scope variable list is required to deal with host variables + // that are equivalenced and requires instantiating the right global + // AggregateStore. + for (auto &hostVariable : pft::getScopeVariableList(*hostScope)) + if ((hostVariable.isAggregateStore() && hostVariable.isGlobal()) || + (hostVariable.hasSymbol() && + globalSymbols.contains(&hostVariable.getSymbol().GetUltimate()))) + Fortran::lower::instantiateVariable(converter, hostVariable, symMap, + storeMap); + } + if (tupleSymbols.empty()) return; // Find the argument with the tuple type. The argument ought to be appended. @@ -534,7 +563,7 @@ mlir::IntegerType offTy = builder.getIntegerType(32); // Walk the list and add the bindings to the symbol table. - for (auto s : llvm::enumerate(symbols)) { + for (auto s : llvm::enumerate(tupleSymbols)) { mlir::Value off = builder.createIntegerConstant(loc, offTy, s.index()); mlir::Type varTy = tupTy.getType(s.index()); mlir::Value eleOff = genTupleCoor(builder, loc, varTy, tupleArg, off); @@ -546,7 +575,7 @@ mlir::Type Fortran::lower::HostAssociations::getArgumentType( Fortran::lower::AbstractConverter &converter) { - if (symbols.empty()) + if (tupleSymbols.empty()) return {}; if (argType) return argType; @@ -555,7 +584,7 @@ // to a tuple. mlir::MLIRContext *ctxt = &converter.getMLIRContext(); llvm::SmallVector tupleTys; - for (const Fortran::semantics::Symbol *sym : symbols) + for (const Fortran::semantics::Symbol *sym : tupleSymbols) tupleTys.emplace_back( walkCaptureCategories(GetTypeInTuple{}, converter, *sym)); argType = fir::ReferenceType::get(mlir::TupleType::get(ctxt, tupleTys)); diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp --- a/flang/lib/Lower/PFTBuilder.cpp +++ b/flang/lib/Lower/PFTBuilder.cpp @@ -1653,6 +1653,12 @@ llvm::report_fatal_error("parent is not a function"); } +bool Fortran::lower::pft::FunctionLikeUnit::parentHasTupleHostAssoc() { + if (auto *par = parent.getIf()) + return par->hostAssociations.hasTupleAssociations(); + return false; +} + bool Fortran::lower::pft::FunctionLikeUnit::parentHasHostAssoc() { if (auto *par = parent.getIf()) return !par->hostAssociations.empty(); diff --git a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp --- a/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp +++ b/flang/lib/Optimizer/Transforms/ArrayValueCopy.cpp @@ -687,7 +687,7 @@ if (auto callee = call.getCallableForCallee().dyn_cast()) { auto module = op->getParentOfType(); - return hasHostAssociationArgument( + return isInternalPorcedure( module.lookupSymbol(callee)); } return false; diff --git a/flang/test/Lower/explicit-interface-results-2.f90 b/flang/test/Lower/explicit-interface-results-2.f90 --- a/flang/test/Lower/explicit-interface-results-2.f90 +++ b/flang/test/Lower/explicit-interface-results-2.f90 @@ -70,7 +70,7 @@ call internal_proc_a() contains ! CHECK-LABEL: func @_QFhost4Pinternal_proc_a -! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.host_assoc}) { +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine internal_proc_a() call takes_array(return_array()) ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 @@ -181,8 +181,6 @@ ! Test internal procedure A calling array internal procedure B. ! Result depends on a common block variable declared in the host. -! Note that the current implementation captures the common block variable -! address, even though it could recompute it in the internal procedure. subroutine host9() implicit none integer :: n_common @@ -190,16 +188,17 @@ call internal_proc_a() contains ! CHECK-LABEL: func @_QFhost9Pinternal_proc_a -! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.host_assoc}) { subroutine internal_proc_a() -! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 -! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref>>, i32) -> !fir.llvm_ptr> -! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.llvm_ptr> -! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] : !fir.ref -! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> index -! CHECK: %[[CMPI:.*]] = arith.cmpi sgt, %[[VAL_5]], %{{.*}} : index -! CHECK: %[[SELECT:.*]] = arith.select %[[CMPI]], %[[VAL_5]], %{{.*}} : index -! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.array, %[[SELECT]] {bindc_name = ".result"} +! CHECK: %[[VAL_0:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_1:.*]] = fir.address_of(@_QBmycom) : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (!fir.ref>) -> !fir.ref> +! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_2]], %[[VAL_0]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ref +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]] : !fir.ref +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> index +! CHECK: %[[VAL_7:.*]] = arith.cmpi sgt, %[[VAL_6]], %[[VAL_0]] : index +! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_6]], %[[VAL_0]] : index +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.array, %[[VAL_8]] {bindc_name = ".result"} call takes_array(return_array()) end subroutine function return_array() diff --git a/flang/test/Lower/host-associated-functions.f90 b/flang/test/Lower/host-associated-functions.f90 --- a/flang/test/Lower/host-associated-functions.f90 +++ b/flang/test/Lower/host-associated-functions.f90 @@ -20,7 +20,7 @@ call internal() contains ! CHECK-LABEL: func @_QFcapture_char_func_dummyPinternal( - ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref ()>, i64>, !fir.ref>> {fir.host_assoc}) { + ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref ()>, i64>, !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine internal() ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref ()>, i64>, !fir.ref>>, i32) -> !fir.ref ()>, i64>> @@ -56,7 +56,7 @@ call internal() contains ! CHECK-LABEL: func @_QFcapture_char_func_assumed_dummyPinternal( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref ()>, i64>>> {fir.host_assoc}) { +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref ()>, i64>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine internal() ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref ()>, i64>>>, i32) -> !fir.ref ()>, i64>> @@ -110,7 +110,7 @@ contains subroutine internal() ! CHECK-LABEL: func @_QFcapture_array_funcPinternal( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.host_assoc}) { +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref>>, i32) -> !fir.llvm_ptr> ! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.llvm_ptr> diff --git a/flang/test/Lower/host-associated-globals.f90 b/flang/test/Lower/host-associated-globals.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/host-associated-globals.f90 @@ -0,0 +1,92 @@ +! Test lowering of internal procedure host association for global variables +! A tuple function argument should not be created for associated globals, and +! instead globals should be instantiated with a fir.address_of inside the +! contained procedures. +! RUN: bbc -emit-fir %s -o - | FileCheck %s + +module test_mod_used_in_host + integer :: i, j_in_equiv + integer :: not_in_equiv + equivalence (i,j_in_equiv) +end module + +subroutine module_var() + use test_mod_used_in_host + call bar() +contains + subroutine bar() + print *, j_in_equiv, not_in_equiv + end subroutine +end subroutine +! CHECK-LABEL: func.func @_QFmodule_varPbar() +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QMtest_mod_used_in_hostEi) : !fir.ref> +! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref) -> !fir.ptr +! CHECK: %[[VAL_4:.*]] = fir.address_of(@_QMtest_mod_used_in_hostEnot_in_equiv) : !fir.ref + +subroutine test_common() + integer, save :: i(2) + integer, save :: j_in_equiv + integer, save :: not_in_equiv + equivalence (i(2),j_in_equiv) + common /x/ i, not_in_equiv + call bar() +contains + subroutine bar() + print *, j_in_equiv, not_in_equiv + end subroutine +end subroutine +! CHECK-LABEL: func.func @_QFtest_commonPbar() attributes {fir.internal_proc} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QBx) : !fir.ref> +! CHECK: %[[VAL_1:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! CHECK: %[[VAL_2:.*]] = arith.constant 4 : index +! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! CHECK: %[[VAL_5:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> +! CHECK: %[[VAL_6:.*]] = arith.constant 8 : index +! CHECK: %[[VAL_7:.*]] = fir.coordinate_of %[[VAL_5]], %[[VAL_6]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.ref) -> !fir.ref + +subroutine saved_equiv() + integer, save :: i(2) + integer, save :: j_in_equiv + integer, save :: not_in_equiv + equivalence (i(2),j_in_equiv) + call bar() +contains + subroutine bar() + print *, j_in_equiv, not_in_equiv + end subroutine +end subroutine +! CHECK-LABEL: func.func @_QFsaved_equivPbar() attributes {fir.internal_proc} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFsaved_equivEi) : !fir.ref> +! CHECK: %[[VAL_1:.*]] = arith.constant 4 : index +! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.ref) -> !fir.ptr +! CHECK: %[[VAL_4:.*]] = fir.address_of(@_QFsaved_equivEnot_in_equiv) : !fir.ref + +subroutine mixed_capture() + integer, save :: saved_i + integer, save :: saved_j + equivalence (saved_i, saved_j) + integer :: i + integer :: j + equivalence (i,j) + call bar() +contains + subroutine bar() + call test(saved_j, j) + end subroutine +end subroutine +! CHECK-LABEL: func.func @_QFmixed_capturePbar( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { +! CHECK: %[[VAL_1:.*]] = fir.address_of(@_QFmixed_captureEsaved_i) : !fir.ref> +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.ref) -> !fir.ptr +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_6:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_5]] : (!fir.ref>>, i32) -> !fir.llvm_ptr> +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_6]] : !fir.llvm_ptr> +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_4]] : (!fir.ptr) -> !fir.ref +! CHECK: fir.call @_QPtest(%[[VAL_9]], %[[VAL_7]]) {{.*}} : (!fir.ref, !fir.ref) -> () diff --git a/flang/test/Lower/host-associated.f90 b/flang/test/Lower/host-associated.f90 --- a/flang/test/Lower/host-associated.f90 +++ b/flang/test/Lower/host-associated.f90 @@ -20,7 +20,7 @@ print *, i contains ! CHECK-LABEL: func @_QFtest1Ptest1_internal( - ! CHECK-SAME: %[[arg:[^:]*]]: !fir.ref>> {fir.host_assoc}) { + ! CHECK-SAME: %[[arg:[^:]*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { ! CHECK: %[[iaddr:.*]] = fir.coordinate_of %[[arg]], %c0 ! CHECK: %[[i:.*]] = fir.load %[[iaddr]] : !fir.llvm_ptr> ! CHECK: %[[val:.*]] = fir.call @_QPifoo() {{.*}}: () -> i32 @@ -47,7 +47,7 @@ print *, a, b contains ! CHECK-LABEL: func @_QFtest2Ptest2_internal( - ! CHECK-SAME: %[[arg:[^:]*]]: !fir.ref, !fir.ref>> {fir.host_assoc}) { + ! CHECK-SAME: %[[arg:[^:]*]]: !fir.ref, !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test2_internal ! CHECK: %[[a:.*]] = fir.coordinate_of %[[arg]], %c0 ! CHECK: %[[aa:.*]] = fir.load %[[a]] : !fir.llvm_ptr> @@ -62,7 +62,7 @@ end subroutine test2_internal ! CHECK-LABEL: func @_QFtest2Ptest2_inner( - ! CHECK-SAME: %[[arg:[^:]*]]: !fir.ref, !fir.ref>> {fir.host_assoc}) { + ! CHECK-SAME: %[[arg:[^:]*]]: !fir.ref, !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test2_inner ! CHECK: %[[a:.*]] = fir.coordinate_of %[[arg]], %c0 ! CHECK: %[[aa:.*]] = fir.load %[[a]] : !fir.llvm_ptr> @@ -96,7 +96,7 @@ contains ! CHECK-LABEL: func @_QFtest6Ptest6_inner( - ! CHECK-SAME: %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) { + ! CHECK-SAME: %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test6_inner ! CHECK: %[[coor:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>>, i32) -> !fir.ref> ! CHECK: %[[load:.*]] = fir.load %[[coor]] : !fir.ref> @@ -138,7 +138,7 @@ contains ! CHECK-LABEL: func @_QFtest3Ptest3_inner( - ! CHECK-SAME: %[[tup:.*]]: !fir.ref>, !fir.box>>> {fir.host_assoc}) { + ! CHECK-SAME: %[[tup:.*]]: !fir.ref>, !fir.box>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test3_inner ! CHECK: %[[pcoor:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>, !fir.box>>>, i32) -> !fir.ref>> ! CHECK: %[[p:.*]] = fir.load %[[pcoor]] : !fir.ref>> @@ -185,7 +185,7 @@ contains ! CHECK: func @_QFtest3aPtest3a_inner( - ! CHECK-SAME: %[[tup:.*]]: !fir.ref>, !fir.box>>> {fir.host_assoc}) { + ! CHECK-SAME: %[[tup:.*]]: !fir.ref>, !fir.box>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test3a_inner ! CHECK: %[[pcoor:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>, !fir.box>>>, i32) -> !fir.ref>> ! CHECK: %[[p:.*]] = fir.load %[[pcoor]] : !fir.ref>> @@ -229,7 +229,7 @@ contains ! CHECK-LABEL: func @_QFtest4Ptest4_inner( - ! CHECK-SAME:%[[tup:.*]]: !fir.ref>>, !fir.ref>>>> {fir.host_assoc}) { + ! CHECK-SAME:%[[tup:.*]]: !fir.ref>>, !fir.ref>>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test4_inner ! CHECK: %[[ptup:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>>, !fir.ref>>>>, i32) -> !fir.llvm_ptr>>> ! CHECK: %[[p:.*]] = fir.load %[[ptup]] : !fir.llvm_ptr>>> @@ -271,7 +271,7 @@ contains ! CHECK-LABEL: func @_QFtest5Ptest5_inner( - ! CHECK-SAME:%[[tup:.*]]: !fir.ref>>>, !fir.ref>>>>> {fir.host_assoc}) { + ! CHECK-SAME:%[[tup:.*]]: !fir.ref>>>, !fir.ref>>>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine test5_inner ! CHECK: %[[ptup:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>>>, !fir.ref>>>>>, i32) -> !fir.llvm_ptr>>>> ! CHECK: %[[p:.*]] = fir.load %[[ptup]] : !fir.llvm_ptr>>>> @@ -309,7 +309,7 @@ contains ! CHECK-LABEL: func @_QFtest7Ptest7_inner( -! CHECK-SAME: %[[i:.*]]: !fir.ref{{.*}}, %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) -> i32 { +! CHECK-SAME: %[[i:.*]]: !fir.ref{{.*}}, %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) -> i32 attributes {fir.internal_proc} { elemental integer function test7_inner(i) implicit none integer, intent(in) :: i @@ -330,7 +330,7 @@ call bar() contains ! CHECK-LABEL: func @_QFissue990Pbar( -! CHECK-SAME: %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) { +! CHECK-SAME: %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine bar() integer :: stmt_func, i stmt_func(i) = i + captured @@ -352,7 +352,7 @@ call bar() contains ! CHECK-LABEL: func @_QFissue990bPbar( -! CHECK-SAME: %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) { +! CHECK-SAME: %[[tup:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine bar() ! CHECK: %[[tupAddr:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>>, i32) -> !fir.llvm_ptr> ! CHECK: %[[addr:.*]] = fir.load %[[tupAddr]] : !fir.llvm_ptr> @@ -373,7 +373,7 @@ call bar() contains ! CHECK-LABEL: func @_QFtest8Pbar( -! CHECK-SAME: %[[tup:.*]]: !fir.ref ()>>> {fir.host_assoc}) { +! CHECK-SAME: %[[tup:.*]]: !fir.ref ()>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine bar() ! CHECK: %[[tupAddr:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref ()>>>, i32) -> !fir.ref ()>> ! CHECK: %[[dummyProc:.*]] = fir.load %[[tupAddr]] : !fir.ref ()>> @@ -393,7 +393,7 @@ call bar() contains ! CHECK-LABEL: func @_QFtest9Pbar( -! CHECK-SAME: %[[tup:.*]]: !fir.ref ()>>> {fir.host_assoc}) { +! CHECK-SAME: %[[tup:.*]]: !fir.ref ()>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine bar() ! CHECK: %[[tupAddr:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref ()>>>, i32) -> !fir.ref ()>> ! CHECK: %[[dummyProc:.*]] = fir.load %[[tupAddr]] : !fir.ref ()>> @@ -416,7 +416,7 @@ call bar() contains ! CHECK-LABEL: func @_QFtest10Pbar( -! CHECK-SAME: %[[tup:.*]]: !fir.ref>>>>> {fir.host_assoc}) { +! CHECK-SAME: %[[tup:.*]]: !fir.ref>>>>> {fir.host_assoc}) attributes {fir.internal_proc} { subroutine bar() ! CHECK: %[[tupAddr:.*]] = fir.coordinate_of %[[tup]], %c0{{.*}} : (!fir.ref>>>>>, i32) -> !fir.llvm_ptr>>>> ! CHECK: fir.load %[[tupAddr]] : !fir.llvm_ptr>>>> @@ -435,7 +435,7 @@ ! CHECK-LABEL: func @_QFtest_proc_dummyPtest_proc_dummy_a( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "j"}, -! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref>> {fir.host_assoc}) { +! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref>> {fir.host_assoc}) attributes {fir.internal_proc} { ! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 ! CHECK: %[[VAL_3:.*]] = fir.coordinate_of %[[VAL_1]], %[[VAL_2]] : (!fir.ref>>, i32) -> !fir.llvm_ptr> ! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] : !fir.llvm_ptr> @@ -529,17 +529,17 @@ ! CHECK-LABEL: func @_QFtest_proc_dummy_charPgen_message( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>, ! CHECK-SAME: %[[VAL_1:.*]]: index, -! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref>> {fir.host_assoc}) -> !fir.boxchar<1> { +! CHECK-SAME: %[[VAL_2:.*]]: !fir.ref>> {fir.host_assoc}) -> !fir.boxchar<1> attributes {fir.internal_proc} { ! CHECK-DAG: %[[VAL_3:.*]] = arith.constant 0 : i32 ! CHECK-DAG: %[[VAL_4:.*]] = arith.constant 10 : index ! CHECK-DAG: %[[VAL_5:.*]] = arith.constant false ! CHECK-DAG: %[[VAL_6:.*]] = arith.constant 1 : index ! CHECK-DAG: %[[VAL_7:.*]] = arith.constant 32 : i8 ! CHECK-DAG: %[[VAL_8:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> ! CHECK: %[[VAL_9:.*]] = fir.coordinate_of %[[VAL_2]], %[[VAL_3]] : (!fir.ref>>, i32) -> !fir.ref> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_9]] : !fir.ref> ! CHECK: %[[VAL_11:.*]]:2 = fir.unboxchar %[[VAL_10]] : (!fir.boxchar<1>) -> (!fir.ref>, index) -! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_0]] : (!fir.ref>) -> !fir.ref> ! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]]#1, %[[VAL_4]] : index ! CHECK: %[[VAL_14:.*]] = arith.select %[[VAL_13]], %[[VAL_4]], %[[VAL_11]]#1 : index ! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (index) -> i64 diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -468,7 +468,7 @@ end subroutine ! CHECK-LABEL: func.func @_QMpolymorphic_testFhost_assocPinternal( -! CHECK-SAME: %[[TUPLE:.*]]: !fir.ref>>> {fir.host_assoc}) { +! CHECK-SAME: %[[TUPLE:.*]]: !fir.ref>>> {fir.host_assoc}) attributes {fir.internal_proc} { ! CHECK: %[[POS_IN_TUPLE:.*]] = arith.constant 0 : i32 ! CHECK: %[[COORD_OF_CLASS:.*]] = fir.coordinate_of %[[TUPLE]], %[[POS_IN_TUPLE]] : (!fir.ref>>>, i32) -> !fir.ref>> ! CHECK: %[[CLASS:.*]] = fir.load %[[COORD_OF_CLASS]] : !fir.ref>>