[flang-commits] [flang] 92e5234 - [flang][hlfir] Lower evaluate::DescriptorInquiry
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Tue Feb 7 06:29:52 PST 2023
Author: Jean Perier
Date: 2023-02-07T15:28:24+01:00
New Revision: 92e5234f696e8a1a2f3242a9d24711005b44a6fc
URL: https://github.com/llvm/llvm-project/commit/92e5234f696e8a1a2f3242a9d24711005b44a6fc
DIFF: https://github.com/llvm/llvm-project/commit/92e5234f696e8a1a2f3242a9d24711005b44a6fc.diff
LOG: [flang][hlfir] Lower evaluate::DescriptorInquiry
Lower extents and lower bounds inquiries with a compile time
constant DIM that cannot be folded by the front-end.
Differential Revision: https://reviews.llvm.org/D143476
Added:
flang/test/Lower/HLFIR/descriptor-inquiries.f90
Modified:
flang/include/flang/Optimizer/Builder/HLFIRTools.h
flang/lib/Lower/ConvertExprToHLFIR.cpp
flang/lib/Optimizer/Builder/HLFIRTools.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index bbc0595a73913..fb1a7547cbe28 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -280,6 +280,16 @@ genBounds(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value shape);
mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity);
+/// Compute the extent of \p entity in dimension \p dim. Crashes
+/// if dim is bigger than the entity's rank.
+mlir::Value genExtent(mlir::Location loc, fir::FirOpBuilder &builder,
+ hlfir::Entity entity, unsigned dim);
+
+/// Compute the lower bound of \p entity in dimension \p dim. Crashes
+/// if dim is bigger than the entity's rank.
+mlir::Value genLBound(mlir::Location loc, fir::FirOpBuilder &builder,
+ hlfir::Entity entity, unsigned dim);
+
/// Generate a vector of extents with index type from a fir.shape
/// of fir.shape_shift value.
llvm::SmallVector<mlir::Value> getIndexExtents(mlir::Location loc,
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index f13822ec55904..7cda0f4345e8c 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1189,9 +1189,11 @@ class HlfirBuilder {
case Fortran::evaluate::DescriptorInquiry::Field::Len:
return castResult(hlfir::genCharLength(loc, builder, entity));
case Fortran::evaluate::DescriptorInquiry::Field::LowerBound:
- TODO(loc, "lower bound inquiry in HLFIR");
+ return castResult(
+ hlfir::genLBound(loc, builder, entity, desc.dimension()));
case Fortran::evaluate::DescriptorInquiry::Field::Extent:
- TODO(loc, "extent inquiry in HLFIR");
+ return castResult(
+ hlfir::genExtent(loc, builder, entity, desc.dimension()));
case Fortran::evaluate::DescriptorInquiry::Field::Rank:
TODO(loc, "rank inquiry on assumed rank");
case Fortran::evaluate::DescriptorInquiry::Field::Stride:
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 7272779ac4338..4b54a0121af3f 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -399,7 +399,7 @@ hlfir::genBounds(mlir::Location loc, fir::FirOpBuilder &builder,
return result;
}
-static hlfir::Entity followEntitySource(hlfir::Entity entity) {
+static hlfir::Entity followShapeInducingSource(hlfir::Entity entity) {
while (true) {
if (auto reassoc = entity.getDefiningOp<hlfir::NoReassocOp>()) {
entity = hlfir::Entity{reassoc.getVal()};
@@ -414,6 +414,24 @@ static hlfir::Entity followEntitySource(hlfir::Entity entity) {
return entity;
}
+static mlir::Value computeVariableExtent(mlir::Location loc,
+ fir::FirOpBuilder &builder,
+ hlfir::Entity variable,
+ fir::SequenceType seqTy,
+ unsigned dim) {
+ mlir::Type idxTy = builder.getIndexType();
+ if (seqTy.getShape().size() > dim) {
+ fir::SequenceType::Extent typeExtent = seqTy.getShape()[dim];
+ if (typeExtent != fir::SequenceType::getUnknownExtent())
+ return builder.createIntegerConstant(loc, idxTy, typeExtent);
+ }
+ assert(variable.getType().isa<fir::BaseBoxType>() &&
+ "array variable with dynamic extent must be boxed");
+ mlir::Value dimVal = builder.createIntegerConstant(loc, idxTy, dim);
+ auto dimInfo = builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy,
+ variable, dimVal);
+ return dimInfo.getExtent();
+}
llvm::SmallVector<mlir::Value> getVariableExtents(mlir::Location loc,
fir::FirOpBuilder &builder,
hlfir::Entity variable) {
@@ -432,42 +450,38 @@ llvm::SmallVector<mlir::Value> getVariableExtents(mlir::Location loc,
fir::SequenceType seqTy =
hlfir::getFortranElementOrSequenceType(variable.getType())
.cast<fir::SequenceType>();
- mlir::Type idxTy = builder.getIndexType();
- for (auto typeExtent : seqTy.getShape())
- if (typeExtent != fir::SequenceType::getUnknownExtent()) {
- extents.push_back(builder.createIntegerConstant(loc, idxTy, typeExtent));
- } else {
- assert(variable.getType().isa<fir::BaseBoxType>() &&
- "array variable with dynamic extent must be boxed");
- mlir::Value dim =
- builder.createIntegerConstant(loc, idxTy, extents.size());
- auto dimInfo = builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy,
- variable, dim);
- extents.push_back(dimInfo.getExtent());
- }
+ unsigned rank = seqTy.getShape().size();
+ for (unsigned dim = 0; dim < rank; ++dim)
+ extents.push_back(
+ computeVariableExtent(loc, builder, variable, seqTy, dim));
return extents;
}
-mlir::Value hlfir::genShape(mlir::Location loc, fir::FirOpBuilder &builder,
- hlfir::Entity entity) {
- assert(entity.isArray() && "entity must be an array");
- entity = followEntitySource(entity);
-
+static mlir::Value tryRetrievingShapeOrShift(hlfir::Entity entity) {
if (entity.getType().isa<hlfir::ExprType>()) {
if (auto elemental = entity.getDefiningOp<hlfir::ElementalOp>())
return elemental.getShape();
- TODO(loc, "get shape from HLFIR expr without producer holding the shape");
+ return mlir::Value{};
}
- // Entity is an array variable.
- if (auto varIface = entity.getIfVariableInterface()) {
- if (auto shape = varIface.getShape()) {
- if (shape.getType().isa<fir::ShapeType>())
- return shape;
- if (shape.getType().isa<fir::ShapeShiftType>())
- if (auto s = shape.getDefiningOp<fir::ShapeShiftOp>())
- return builder.create<fir::ShapeOp>(loc, s.getExtents());
- }
+ if (auto varIface = entity.getIfVariableInterface())
+ return varIface.getShape();
+ return {};
+}
+
+mlir::Value hlfir::genShape(mlir::Location loc, fir::FirOpBuilder &builder,
+ hlfir::Entity entity) {
+ assert(entity.isArray() && "entity must be an array");
+ entity = followShapeInducingSource(entity);
+ assert(entity && "what?");
+ if (auto shape = tryRetrievingShapeOrShift(entity)) {
+ if (shape.getType().isa<fir::ShapeType>())
+ return shape;
+ if (shape.getType().isa<fir::ShapeShiftType>())
+ if (auto s = shape.getDefiningOp<fir::ShapeShiftOp>())
+ return builder.create<fir::ShapeOp>(loc, s.getExtents());
}
+ if (entity.getType().isa<hlfir::ExprType>())
+ TODO(loc, "get shape from HLFIR expr without producer holding the shape");
// There is no shape lying around for this entity. Retrieve the extents and
// build a new fir.shape.
return builder.create<fir::ShapeOp>(loc,
@@ -484,6 +498,50 @@ hlfir::getIndexExtents(mlir::Location loc, fir::FirOpBuilder &builder,
return extents;
}
+mlir::Value hlfir::genExtent(mlir::Location loc, fir::FirOpBuilder &builder,
+ hlfir::Entity entity, unsigned dim) {
+ entity = followShapeInducingSource(entity);
+ if (auto shape = tryRetrievingShapeOrShift(entity)) {
+ auto extents = getExplicitExtentsFromShape(shape);
+ if (!extents.empty()) {
+ assert(extents.size() > dim && "bad inquiry");
+ return extents[dim];
+ }
+ }
+ if (entity.isVariable()) {
+ if (entity.isMutableBox())
+ entity = hlfir::derefPointersAndAllocatables(loc, builder, entity);
+ // Use the type shape information, and/or the fir.box/fir.class shape
+ // information if any extents are not static.
+ fir::SequenceType seqTy =
+ hlfir::getFortranElementOrSequenceType(entity.getType())
+ .cast<fir::SequenceType>();
+ return computeVariableExtent(loc, builder, entity, seqTy, dim);
+ }
+ TODO(loc, "get extent from HLFIR expr without producer holding the shape");
+}
+
+mlir::Value hlfir::genLBound(mlir::Location loc, fir::FirOpBuilder &builder,
+ hlfir::Entity entity, unsigned dim) {
+ if (!entity.hasNonDefaultLowerBounds())
+ return builder.createIntegerConstant(loc, builder.getIndexType(), 1);
+ if (auto shape = tryRetrievingShapeOrShift(entity)) {
+ auto lbounds = getExplicitLboundsFromShape(shape);
+ if (!lbounds.empty()) {
+ assert(lbounds.size() > dim && "bad inquiry");
+ return lbounds[dim];
+ }
+ }
+ if (entity.isMutableBox())
+ entity = hlfir::derefPointersAndAllocatables(loc, builder, entity);
+ assert(entity.getType().isa<fir::BaseBoxType>() && "must be a box");
+ mlir::Type idxTy = builder.getIndexType();
+ mlir::Value dimVal = builder.createIntegerConstant(loc, idxTy, dim);
+ auto dimInfo =
+ builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, entity, dimVal);
+ return dimInfo.getLowerBound();
+}
+
void hlfir::genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity,
llvm::SmallVectorImpl<mlir::Value> &result) {
diff --git a/flang/test/Lower/HLFIR/descriptor-inquiries.f90 b/flang/test/Lower/HLFIR/descriptor-inquiries.f90
new file mode 100644
index 0000000000000..ecdec0ac8e507
--- /dev/null
+++ b/flang/test/Lower/HLFIR/descriptor-inquiries.f90
@@ -0,0 +1,85 @@
+! Test lowering of extent and lower bound inquires that
+! come in lowering as evaluate::DescriptorInquiry.
+
+! RUN: bbc -emit-fir -hlfir -o - %s | FileCheck %s
+
+subroutine test_assumed_shape(x, r)
+ integer(8) :: r
+ real :: x(:,:)
+ r = size(x, dim=2, kind=8)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_assumed_shape(
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare {{.*}}Ex
+! CHECK: %[[VAL_4:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]]#1 : (index) -> i64
+! CHECK: hlfir.assign %[[VAL_6]] to %{{.*}}
+
+subroutine test_explicit_shape(x, n, m, r)
+ integer(8) :: n, m, r
+ real :: x(n,m)
+ r = size(x, dim=2, kind=8)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_explicit_shape(
+! CHECK: %[[VAL_17:.*]] = fir.shape %{{.*}}, %[[VAL_16:.*]] : (index, index) -> !fir.shape<2>
+! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_17]]) {{.*}}Ex
+! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_16]] : (index) -> i64
+! CHECK: hlfir.assign %[[VAL_19]] to %{{.*}}
+
+subroutine test_pointer(x, r)
+ integer(8) :: r
+ real :: x(:,:)
+ r = size(x, dim=2, kind=8)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_pointer(
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare {{.*}}Ex
+! CHECK: %[[VAL_4:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_4]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]]#1 : (index) -> i64
+! CHECK: hlfir.assign %[[VAL_6]] to %{{.*}}
+
+subroutine test_lbound_assumed_shape(x, l1, l2, r)
+ integer(8) :: l1, l2, r
+ real :: x(l1:,l2:)
+ r = lbound(x, dim=2, kind=8)
+end subroutine
+! CHECK: %[[VAL_11:.*]] = fir.shift %[[VAL_8:.*]], %[[VAL_10:.*]] : (index, index) -> !fir.shift<2>
+! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_11]]) {{.*}}Ex
+! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i64
+! CHECK: %[[VAL_14:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_16:.*]]:3 = fir.box_dims %[[VAL_12]]#1, %[[VAL_15]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+! CHECK: %[[VAL_17:.*]] = arith.cmpi eq, %[[VAL_16]]#1, %[[VAL_14]] : index
+! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_13]] : (i64) -> index
+! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_17]], %[[VAL_18]], %[[VAL_10]] : index
+! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (index) -> i64
+! CHECK: hlfir.assign %[[VAL_20]] to %{{.*}}
+
+subroutine test_lbound_explicit_shape(x, n, m, l1, l2, r)
+ integer(8) :: n, m, l1, l2, r
+ real :: x(l1:n,l2:m)
+ r = lbound(x, dim=2, kind=8)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_lbound_explicit_shape(
+! CHECK: %[[VAL_31:.*]] = fir.shape_shift %{{.*}}, %{{.*}}, %[[VAL_22:.*]], %[[VAL_30:.*]] : (index, index, index, index) -> !fir.shapeshift<2>
+! CHECK: %[[VAL_32:.*]]:2 = hlfir.declare %{{.*}}(%[[VAL_31]]) {{.*}}Ex
+! CHECK: %[[VAL_33:.*]] = arith.constant 1 : i64
+! CHECK: %[[VAL_34:.*]] = arith.constant 0 : index
+! CHECK: %[[VAL_35:.*]] = arith.cmpi eq, %[[VAL_30]], %[[VAL_34]] : index
+! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_33]] : (i64) -> index
+! CHECK: %[[VAL_37:.*]] = arith.select %[[VAL_35]], %[[VAL_36]], %[[VAL_22]] : index
+! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (index) -> i64
+! CHECK: hlfir.assign %[[VAL_38]] to %{{.*}}
+
+subroutine test_lbound_pointer(x, r)
+ integer(8) :: r
+ real, pointer :: x(:,:)
+ r = lbound(x, dim=2, kind=8)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_lbound_pointer(
+! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare {{.*}}Ex
+! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>
+! CHECK: %[[VAL_5:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_4]], %[[VAL_5]] : (!fir.box<!fir.ptr<!fir.array<?x?xf32>>>, index) -> (index, index, index)
+! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]]#0 : (index) -> i64
+! CHECK: hlfir.assign %[[VAL_7]] to %{{.*}}
More information about the flang-commits
mailing list