[flang-commits] [flang] 3508f69 - [flang][hlfir] Lower whole allocatable or pointer component ref
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Thu Jan 19 07:58:16 PST 2023
Author: Jean Perier
Date: 2023-01-19T16:57:21+01:00
New Revision: 3508f69174e663d276b58c55e176688f828591ac
URL: https://github.com/llvm/llvm-project/commit/3508f69174e663d276b58c55e176688f828591ac
DIFF: https://github.com/llvm/llvm-project/commit/3508f69174e663d276b58c55e176688f828591ac.diff
LOG: [flang][hlfir] Lower whole allocatable or pointer component ref
Compare to other component ref lowering, the hlfir.designate result type
computation is different, and the allocatable/pointer/contiguous must
be set on the hlfir.designate so that the component attributes are
kept in the IR.
Differential Revision: https://reviews.llvm.org/D142111
Added:
flang/test/Lower/HLFIR/allocatable-and-pointer-components.f90
Modified:
flang/include/flang/Lower/ConvertVariable.h
flang/lib/Lower/ConvertExprToHLFIR.cpp
flang/lib/Lower/ConvertVariable.cpp
flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/ConvertVariable.h b/flang/include/flang/Lower/ConvertVariable.h
index 0e2932fa1ab85..a77dcedea9020 100644
--- a/flang/include/flang/Lower/ConvertVariable.h
+++ b/flang/include/flang/Lower/ConvertVariable.h
@@ -25,6 +25,7 @@ namespace fir {
class ExtendedValue;
class FirOpBuilder;
class GlobalOp;
+class FortranVariableFlagsAttr;
} // namespace fir
namespace Fortran ::lower {
@@ -110,5 +111,10 @@ void createRuntimeTypeInfoGlobal(Fortran::lower::AbstractConverter &converter,
mlir::Location loc,
const Fortran::semantics::Symbol &typeInfoSym);
+/// Translate the Fortran attributes of \p sym into the FIR variable attribute
+/// representation.
+fir::FortranVariableFlagsAttr
+translateSymbolAttributes(mlir::MLIRContext *mlirContext,
+ const Fortran::semantics::Symbol &sym);
} // namespace Fortran::lower
#endif // FORTRAN_LOWER_CONVERT_VARIABLE_H
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 566840c62ba1f..09c4c7a20e6fd 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -17,6 +17,7 @@
#include "flang/Lower/ConvertCall.h"
#include "flang/Lower/ConvertConstant.h"
#include "flang/Lower/ConvertType.h"
+#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/IntrinsicCall.h"
#include "flang/Lower/StatementContext.h"
#include "flang/Lower/SymbolMap.h"
@@ -136,12 +137,17 @@ class HlfirDesignatorBuilder {
const T &designatorNode) {
mlir::Type designatorType =
computeDesignatorType(resultValueType, partInfo, designatorNode);
+ return genDesignate(designatorType, partInfo, /*attributes=*/{});
+ }
+ fir::FortranVariableOpInterface
+ genDesignate(mlir::Type designatorType, PartInfo &partInfo,
+ fir::FortranVariableFlagsAttr attributes) {
std::optional<bool> complexPart;
auto designate = getBuilder().create<hlfir::DesignateOp>(
getLoc(), designatorType, partInfo.base.getBase(),
partInfo.componentName, partInfo.componentShape, partInfo.subscripts,
partInfo.substring, complexPart, partInfo.resultShape,
- partInfo.typeParams);
+ partInfo.typeParams, attributes);
return mlir::cast<fir::FortranVariableOpInterface>(
designate.getOperation());
}
@@ -157,6 +163,17 @@ class HlfirDesignatorBuilder {
fir::FortranVariableOpInterface
gen(const Fortran::evaluate::Component &component) {
PartInfo partInfo;
+ if (Fortran::semantics::IsAllocatableOrPointer(component.GetLastSymbol())) {
+ // Generate whole allocatable or pointer component reference. The
+ // hlfir.designate result will be a pointer/allocatable.
+ auto [_, componentType] = visitComponentImpl(
+ component, partInfo, /*dereferencePointerAndAllocComponents=*/false);
+ mlir::Type designatorType = fir::ReferenceType::get(componentType);
+ fir::FortranVariableFlagsAttr attributes =
+ Fortran::lower::translateSymbolAttributes(getBuilder().getContext(),
+ component.GetLastSymbol());
+ return genDesignate(designatorType, partInfo, attributes);
+ }
mlir::Type resultType = visit(component, partInfo);
return genDesignate(resultType, partInfo, component);
}
@@ -280,7 +297,8 @@ class HlfirDesignatorBuilder {
PartInfo &partInfo) {
mlir::Type baseType;
if (const auto *component = arrayRef.base().UnwrapComponent())
- baseType = visitComponentImpl(*component, partInfo).second;
+ baseType = hlfir::getFortranElementOrSequenceType(
+ visitComponentImpl(*component, partInfo).second);
else
baseType = visit(arrayRef.base().GetLastSymbol(), partInfo);
@@ -428,6 +446,8 @@ class HlfirDesignatorBuilder {
// array. The code below determines the shape of the component reference if
// any.
auto [baseType, componentType] = visitComponentImpl(component, partInfo);
+ mlir::Type componentBaseType =
+ hlfir::getFortranElementOrSequenceType(componentType);
if (partInfo.base.isArray()) {
// For array%scalar_comp, the result shape is
// the one of the base. Compute it here. Note that the lower bounds of the
@@ -436,13 +456,13 @@ class HlfirDesignatorBuilder {
partInfo.resultShape = hlfir::genShape(loc, getBuilder(), partInfo.base);
assert(!partInfo.componentShape &&
"Fortran designators can only have one ranked part");
- return changeElementType(baseType, componentType);
+ return changeElementType(baseType, componentBaseType);
}
// scalar%array_comp or scalar%scalar. In any case the shape of this
// part-ref is coming from the component.
partInfo.resultShape = partInfo.componentShape;
partInfo.componentShape = {};
- return componentType;
+ return componentBaseType;
}
// Returns the <BaseType, ComponentType> pair, computes partInfo.base,
@@ -451,7 +471,8 @@ class HlfirDesignatorBuilder {
// processing a following ArrayRef, if any, and in "visit" otherwise.
std::pair<mlir::Type, mlir::Type>
visitComponentImpl(const Fortran::evaluate::Component &component,
- PartInfo &partInfo) {
+ PartInfo &partInfo,
+ bool dereferencePointerAndAllocComponents = true) {
fir::FirOpBuilder &builder = getBuilder();
// Break the Designator visit here: if the base is an array-ref, a
// coarray-ref, or another component, this creates another hlfir.designate
@@ -473,10 +494,11 @@ class HlfirDesignatorBuilder {
if (recordType.isDependentType())
TODO(getLoc(), "Designate derived type with length parameters in HLFIR");
mlir::Type fieldType = recordType.getType(partInfo.componentName);
- fieldType = hlfir::getFortranElementOrSequenceType(fieldType);
- partInfo.componentShape = genComponentShape(componentSym, fieldType);
+ mlir::Type fieldBaseType =
+ hlfir::getFortranElementOrSequenceType(fieldType);
+ partInfo.componentShape = genComponentShape(componentSym, fieldBaseType);
- mlir::Type fieldEleType = hlfir::getFortranElementType(fieldType);
+ mlir::Type fieldEleType = hlfir::getFortranElementType(fieldBaseType);
if (fir::isRecordWithTypeParameters(fieldEleType))
TODO(loc,
"lower a component that is a parameterized derived type to HLFIR");
@@ -496,7 +518,8 @@ class HlfirDesignatorBuilder {
// For pointers and allocatables, if there is a substring, complex part or
// array ref, the designator should be broken here and the pointer or
// allocatable dereferenced.
- if (Fortran::semantics::IsAllocatableOrPointer(componentSym))
+ if (Fortran::semantics::IsAllocatableOrPointer(componentSym) &&
+ dereferencePointerAndAllocComponents)
TODO(loc, "lowering ref to allocatable or pointer component to HLFIR");
return {baseType, fieldType};
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index fff076bb05498..83b56567d5f24 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1311,9 +1311,8 @@ recoverShapeVector(llvm::ArrayRef<std::int64_t> shapeVec, mlir::Value initVal) {
return result;
}
-static fir::FortranVariableFlagsAttr
-translateSymbolAttributes(mlir::MLIRContext *mlirContext,
- const Fortran::semantics::Symbol &sym) {
+fir::FortranVariableFlagsAttr Fortran::lower::translateSymbolAttributes(
+ mlir::MLIRContext *mlirContext, const Fortran::semantics::Symbol &sym) {
fir::FortranVariableFlagsEnum flags = fir::FortranVariableFlagsEnum::None;
const auto &attrs = sym.attrs();
if (attrs.test(Fortran::semantics::Attr::ALLOCATABLE))
@@ -1372,7 +1371,7 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
lenParams.emplace_back(len);
auto name = Fortran::lower::mangle::mangleName(sym);
fir::FortranVariableFlagsAttr attributes =
- translateSymbolAttributes(builder.getContext(), sym);
+ Fortran::lower::translateSymbolAttributes(builder.getContext(), sym);
auto newBase = builder.create<hlfir::DeclareOp>(
loc, base, name, shapeOrShift, lenParams, attributes);
symMap.addVariableDefinition(sym, newBase, force);
@@ -1411,7 +1410,7 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
const mlir::Location loc = genLocation(converter, sym);
fir::FortranVariableFlagsAttr attributes =
- translateSymbolAttributes(builder.getContext(), sym);
+ Fortran::lower::translateSymbolAttributes(builder.getContext(), sym);
auto name = Fortran::lower::mangle::mangleName(sym);
hlfir::EntityWithAttributes declare =
hlfir::genDeclare(loc, builder, exv, name, attributes);
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index c426cddbd135e..5487defb69dc5 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -214,11 +214,19 @@ class DesignateOpConversion
// - scalar%array(indices) [substring| complex part]
mlir::Type componentType = baseEleTy.cast<fir::RecordType>().getType(
designate.getComponent().value());
- if (componentType.isa<fir::BaseBoxType>())
- TODO(loc,
- "addressing parametrized derived type automatic components");
mlir::Type coorTy = fir::ReferenceType::get(componentType);
base = builder.create<fir::CoordinateOp>(loc, coorTy, base, fieldIndex);
+ if (componentType.isa<fir::BaseBoxType>()) {
+ auto variableInterface = mlir::cast<fir::FortranVariableOpInterface>(
+ designate.getOperation());
+ if (variableInterface.isAllocatable() ||
+ variableInterface.isPointer()) {
+ rewriter.replaceOp(designate, base);
+ return mlir::success();
+ }
+ TODO(loc,
+ "addressing parametrized derived type automatic components");
+ }
baseEleTy = hlfir::getFortranElementType(componentType);
shape = designate.getComponentShape();
} else {
diff --git a/flang/test/Lower/HLFIR/allocatable-and-pointer-components.f90 b/flang/test/Lower/HLFIR/allocatable-and-pointer-components.f90
new file mode 100644
index 0000000000000..c29b62aef251d
--- /dev/null
+++ b/flang/test/Lower/HLFIR/allocatable-and-pointer-components.f90
@@ -0,0 +1,119 @@
+! Test lowering of whole allocatable and pointer components to HLFIR
+! RUN: bbc -emit-fir -hlfir -o - %s -I nw | FileCheck %s
+
+module def_test_types
+ type t1
+ real, pointer :: p(:)
+ end type
+ type t2
+ real, allocatable :: a(:)
+ end type
+ type t3
+ real, pointer, contiguous :: p_contiguous(:)
+ end type
+ type t4
+ character(:), pointer :: char_p(:)
+ end type
+ type t5
+ character(10), allocatable :: char_a(:)
+ end type
+ interface
+ subroutine takes_pointer(y)
+ real, pointer :: y(:)
+ end subroutine
+ subroutine takes_contiguous_pointer(y)
+ real, pointer, contiguous :: y(:)
+ end subroutine
+ subroutine takes_allocatable(y)
+ real, allocatable :: y(:)
+ end subroutine
+ subroutine takes_char_pointer(y)
+ character(:), pointer :: y(:)
+ end subroutine
+ subroutine takes_char_alloc_cst_len(y)
+ character(10), allocatable :: y(:)
+ end subroutine
+ subroutine takes_array(y)
+ real :: y(*)
+ end subroutine
+ subroutine takes_char_array(y)
+ character(*) :: y(*)
+ end subroutine
+
+ end interface
+end module
+
+subroutine passing_pointer(x)
+ use def_test_types
+ implicit none
+ type(t1) :: x
+ call takes_pointer(x%p)
+end subroutine
+! CHECK-LABEL: func.func @_QPpassing_pointer(
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
+! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMdef_test_typesTt1{p:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: fir.call @_QPtakes_pointer(%[[VAL_2]]) {{.*}}: (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> ()
+
+subroutine passing_allocatable(x)
+ use def_test_types
+ implicit none
+ type(t2) :: x
+ call takes_allocatable(x%a)
+ call takes_array(x%a)
+end subroutine
+! CHECK-LABEL: func.func @_QPpassing_allocatable(
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
+! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"a"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMdef_test_typesTt2{a:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: fir.call @_QPtakes_allocatable(%[[VAL_2]]) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> ()
+! CHECK: %[[VAL_3:.*]] = hlfir.designate %[[VAL_1]]#0{"a"} {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMdef_test_typesTt2{a:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: fir.call @_QPtakes_array(%[[VAL_6]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
+
+subroutine passing_contiguous_pointer(x)
+ use def_test_types
+ type(t3) :: x
+ call takes_contiguous_pointer(x%p_contiguous)
+ call takes_array(x%p_contiguous)
+end subroutine
+! CHECK-LABEL: func.func @_QPpassing_contiguous_pointer(
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
+! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"p_contiguous"} {fortran_attrs = #fir.var_attrs<contiguous, pointer>} : (!fir.ref<!fir.type<_QMdef_test_typesTt3{p_contiguous:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: fir.call @_QPtakes_contiguous_pointer(%[[VAL_2]]) {{.*}}: (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> ()
+! CHECK: %[[VAL_3:.*]] = hlfir.designate %[[VAL_1]]#0{"p_contiguous"} {fortran_attrs = #fir.var_attrs<contiguous, pointer>} : (!fir.ref<!fir.type<_QMdef_test_typesTt3{p_contiguous:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.ptr<!fir.array<?xf32>>
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (!fir.ptr<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: fir.call @_QPtakes_array(%[[VAL_6]]) {{.*}}: (!fir.ref<!fir.array<?xf32>>) -> ()
+
+subroutine passing_char_pointer(x)
+ use def_test_types
+ implicit none
+ type(t4) :: x
+ call takes_char_pointer(x%char_p)
+end subroutine
+! CHECK-LABEL: func.func @_QPpassing_char_pointer(
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
+! CHECK: %[[VAL_2:.*]] = hlfir.designate %[[VAL_1]]#0{"char_p"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMdef_test_typesTt4{char_p:!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
+! CHECK: fir.call @_QPtakes_char_pointer(%[[VAL_2]]) {{.*}}: (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>) -> ()
+
+subroutine passing_char_alloc_cst_len(x)
+ use def_test_types
+ implicit none
+ type(t5) :: x
+ call takes_char_alloc_cst_len(x%char_a)
+ call takes_char_array(x%char_a)
+end subroutine
+! CHECK-LABEL: func.func @_QPpassing_char_alloc_cst_len(
+! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:[a-z0-9]*]] {{.*}}Ex
+! CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_3:.*]] = hlfir.designate %[[VAL_1]]#0{"char_a"} typeparams %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMdef_test_typesTt5{char_a:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
+! CHECK: fir.call @_QPtakes_char_alloc_cst_len(%[[VAL_3]]) {{.*}}: (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>) -> ()
+! CHECK: %[[VAL_4:.*]] = arith.constant 10 : index
+! CHECK: %[[VAL_5:.*]] = hlfir.designate %[[VAL_1]]#0{"char_a"} typeparams %[[VAL_4]] {fortran_attrs = #fir.var_attrs<allocatable>} : (!fir.ref<!fir.type<_QMdef_test_typesTt5{char_a:!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>}>>, index) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
+! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>>
+! CHECK: %[[VAL_7:.*]] = fir.box_addr %[[VAL_6]] : (!fir.box<!fir.heap<!fir.array<?x!fir.char<1,10>>>>) -> !fir.heap<!fir.array<?x!fir.char<1,10>>>
+! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,10>>
+! CHECK: %[[VAL_9:.*]] = fir.emboxchar %[[VAL_8]], %[[VAL_4]] : (!fir.ref<!fir.char<1,10>>, index) -> !fir.boxchar<1>
+! CHECK: fir.call @_QPtakes_char_array(%[[VAL_9]]) {{.*}}: (!fir.boxchar<1>) -> ()
More information about the flang-commits
mailing list