[flang] improve and rename Entity::hasNonDefaultLowerBounds (#93848)

Improve hasNonDefaultLowerBounds to follow box fir.convert. This helps
HLFIR helpers to generate less code when it can be easily deduced that
the fir.box lower bounds were set to ones.

It will help me for SELECT RANK lowering to avoid generating
hlfir.declare with lower bounds inside the RANK CASE (Current situation
would not be incorrect, the lower bounds would be SSA value ending-up
being one, I just want simpler IR).

Renamed to mayHaveNonDefaultLowerBounds since it may still answer yes when
the lower bounds are ones.
This commit is contained in:
jeanPerier 2024-05-31 13:41:11 +02:00 committed by GitHub
parent 8f4d5a32ac
commit f917c396c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 39 additions and 47 deletions

View File

@ -116,21 +116,7 @@ public:
return fir::isRecordWithTypeParameters(getFortranElementType());
}
bool hasNonDefaultLowerBounds() const {
if (!isBoxAddressOrValue() || isScalar())
return false;
if (isMutableBox())
return true;
if (auto varIface = getIfVariableInterface()) {
if (auto shape = varIface.getShape()) {
auto shapeTy = shape.getType();
return mlir::isa<fir::ShiftType>(shapeTy) ||
mlir::isa<fir::ShapeShiftType>(shapeTy);
}
return false;
}
return true;
}
bool mayHaveNonDefaultLowerBounds() const;
// Is this entity known to be contiguous at compile time?
// Note that when this returns false, the entity may still

View File

@ -151,7 +151,7 @@ public:
}
extents.push_back(builder.createIntegerConstant(loc, idxTy, extent));
}
if (!hasNonDefaultLowerBounds(componentSym))
if (!mayHaveNonDefaultLowerBounds(componentSym))
return builder.create<fir::ShapeOp>(loc, extents);
llvm::SmallVector<mlir::Value> lbounds;
@ -215,7 +215,7 @@ private:
// Arrays with non default lower bounds or dynamic length or dynamic extent
// need a fir.box to hold the dynamic or lower bound information.
if (fir::hasDynamicSize(resultValueType) ||
hasNonDefaultLowerBounds(partInfo))
mayHaveNonDefaultLowerBounds(partInfo))
return fir::BoxType::get(resultValueType);
// Non simply contiguous ref require a fir.box to carry the byte stride.
if (mlir::isa<fir::SequenceType>(resultValueType) &&
@ -600,7 +600,7 @@ private:
}
static bool
hasNonDefaultLowerBounds(const Fortran::semantics::Symbol &componentSym) {
mayHaveNonDefaultLowerBounds(const Fortran::semantics::Symbol &componentSym) {
if (const auto *objDetails =
componentSym.detailsIf<Fortran::semantics::ObjectEntityDetails>())
for (const Fortran::semantics::ShapeSpec &bounds : objDetails->shape())
@ -610,7 +610,7 @@ private:
return true;
return false;
}
static bool hasNonDefaultLowerBounds(const PartInfo &partInfo) {
static bool mayHaveNonDefaultLowerBounds(const PartInfo &partInfo) {
return partInfo.resultShape &&
mlir::isa<fir::ShiftType, fir::ShapeShiftType>(
partInfo.resultShape.getType());

View File

@ -115,7 +115,7 @@ genLboundsAndExtentsFromBox(mlir::Location loc, fir::FirOpBuilder &builder,
static llvm::SmallVector<mlir::Value>
getNonDefaultLowerBounds(mlir::Location loc, fir::FirOpBuilder &builder,
hlfir::Entity entity) {
if (!entity.hasNonDefaultLowerBounds())
if (!entity.mayHaveNonDefaultLowerBounds())
return {};
if (auto varIface = entity.getIfVariableInterface()) {
llvm::SmallVector<mlir::Value> lbounds = getExplicitLbounds(varIface);
@ -195,6 +195,29 @@ mlir::Value hlfir::Entity::getFirBase() const {
return getBase();
}
static bool isShapeWithLowerBounds(mlir::Value shape) {
if (!shape)
return false;
auto shapeTy = shape.getType();
return mlir::isa<fir::ShiftType>(shapeTy) ||
mlir::isa<fir::ShapeShiftType>(shapeTy);
}
bool hlfir::Entity::mayHaveNonDefaultLowerBounds() const {
if (!isBoxAddressOrValue() || isScalar())
return false;
if (isMutableBox())
return true;
if (auto varIface = getIfVariableInterface())
return isShapeWithLowerBounds(varIface.getShape());
// Go through chain of fir.box converts.
if (auto convert = getDefiningOp<fir::ConvertOp>())
return hlfir::Entity{convert.getValue()}.mayHaveNonDefaultLowerBounds();
// TODO: Embox and Rebox do not have hlfir variable interface, but are
// easy to reason about.
return true;
}
fir::FortranVariableOpInterface
hlfir::genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
const fir::ExtendedValue &exv, llvm::StringRef name,
@ -571,7 +594,7 @@ mlir::Value hlfir::genExtent(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Value hlfir::genLBound(mlir::Location loc, fir::FirOpBuilder &builder,
hlfir::Entity entity, unsigned dim) {
if (!entity.hasNonDefaultLowerBounds())
if (!entity.mayHaveNonDefaultLowerBounds())
return builder.createIntegerConstant(loc, builder.getIndexType(), 1);
if (auto shape = tryRetrievingShapeOrShift(entity)) {
auto lbounds = getExplicitLboundsFromShape(shape);
@ -891,7 +914,8 @@ static fir::ExtendedValue translateVariableToExtendedValue(
llvm::SmallVector<mlir::Value> extents;
llvm::SmallVector<mlir::Value> nonDefaultLbounds;
if (mlir::isa<fir::BaseBoxType>(variable.getType()) &&
!variable.getIfVariableInterface()) {
!variable.getIfVariableInterface() &&
variable.mayHaveNonDefaultLowerBounds()) {
// This special case avoids generating two sets of identical
// fir.box_dim to get both the lower bounds and extents.
genLboundsAndExtentsFromBox(loc, builder, variable, nonDefaultLbounds,
@ -1219,7 +1243,7 @@ hlfir::genTypeAndKindConvert(mlir::Location loc, fir::FirOpBuilder &builder,
hlfir::genElementalOp(loc, builder, toType, shape, lenParams, genKernel,
/*isUnordered=*/true);
if (preserveLowerBounds && source.hasNonDefaultLowerBounds()) {
if (preserveLowerBounds && source.mayHaveNonDefaultLowerBounds()) {
hlfir::AssociateOp associate =
genAssociateExpr(loc, builder, hlfir::Entity{convertedRhs},
convertedRhs.getType(), ".tmp.keeplbounds");

View File

@ -47,10 +47,7 @@ func.func @_QPtest(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "array"}
// CHECK-NEXT: %[[V17:.*]] = arith.cmpi sge, %[[V16]], %[[V4]] : i32
// CHECK-NEXT: %[[V18:.*]] = fir.if %[[V17]] -> (i32) {
// CHECK-NEXT: %[[ISFIRST:.*]] = fir.load %[[V0]] : !fir.ref<i32>
// CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %[[V1]]#0, %c0 : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
// CHECK-NEXT: %[[SUB:.*]] = arith.subi %[[DIMS]]#0, %c1 : index
// CHECK-NEXT: %[[ADD:.*]] = arith.addi %[[V14]], %[[SUB]] : index
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[ADD]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V20:.*]] = fir.load %[[V19]] : !fir.ref<i32>
// CHECK-NEXT: %[[V21:.*]] = arith.cmpi sgt, %[[V20]], %arg4 : i32
// CHECK-NEXT: %[[ISFIRSTL:.*]] = fir.convert %[[ISFIRST]] : (i32) -> i1
@ -114,10 +111,7 @@ func.func @_QPtest_float(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a
// CHECK-NEXT: %[[V17:.*]] = arith.cmpf oge, %[[V16]], %[[V4:.*]] : f32
// CHECK-NEXT: %[[V18:.*]] = fir.if %[[V17]] -> (f32) {
// CHECK-NEXT: %[[ISFIRST:.*]] = fir.load %[[V0:.*]] : !fir.ref<i32>
// CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %2#0, %c0 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
// CHECK-NEXT: %[[SUB:.*]] = arith.subi %[[DIMS]]#0, %c1 : index
// CHECK-NEXT: %[[ADD:.*]] = arith.addi %[[V14]], %[[SUB]] : index
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[ADD]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
// CHECK-NEXT: %[[V20:.*]] = fir.load %[[V19]] : !fir.ref<f32>
// CHECK-NEXT: %[[NEW_MIN:.*]] = arith.cmpf ogt, %[[V20]], %arg4 fastmath<contract> : f32
// CHECK-NEXT: %[[CONDRED:.*]] = arith.cmpf une, %arg4, %arg4 fastmath<contract> : f32

View File

@ -47,10 +47,7 @@ func.func @_QPtest(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "array"}
// CHECK-NEXT: %[[V17:.*]] = arith.cmpi sge, %[[V16]], %[[V4]] : i32
// CHECK-NEXT: %[[V18:.*]] = fir.if %[[V17]] -> (i32) {
// CHECK-NEXT: %[[ISFIRST:.*]] = fir.load %[[V0]] : !fir.ref<i32>
// CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %[[V1]]#0, %c0 : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
// CHECK-NEXT: %[[SUB:.*]] = arith.subi %[[DIMS]]#0, %c1 : index
// CHECK-NEXT: %[[ADD:.*]] = arith.addi %[[V14]], %[[SUB]] : index
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[ADD]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V20:.*]] = fir.load %[[V19]] : !fir.ref<i32>
// CHECK-NEXT: %[[V21:.*]] = arith.cmpi slt, %[[V20]], %arg4 : i32
// CHECK-NEXT: %[[ISFIRSTL:.*]] = fir.convert %[[ISFIRST]] : (i32) -> i1
@ -129,10 +126,7 @@ func.func @_QPtest_kind2(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a
// CHECK-NEXT: %[[V17:.*]] = arith.cmpi sge, %[[V16]], %[[V4]] : i32
// CHECK-NEXT: %[[V18:.*]] = fir.if %[[V17]] -> (i32) {
// CHECK-NEXT: %[[ISFIRST:.*]] = fir.load %[[V0]] : !fir.ref<i16>
// CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %[[V1]]#0, %c0 : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
// CHECK-NEXT: %[[SUB:.*]] = arith.subi %[[DIMS]]#0, %c1 : index
// CHECK-NEXT: %[[ADD:.*]] = arith.addi %[[V14]], %[[SUB]] : index
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[ADD]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V20:.*]] = fir.load %[[V19]] : !fir.ref<i32>
// CHECK-NEXT: %[[V21:.*]] = arith.cmpi slt, %[[V20]], %arg4 : i32
// CHECK-NEXT: %[[ISFIRSTL:.*]] = fir.convert %[[ISFIRST]] : (i16) -> i1
@ -222,10 +216,7 @@ func.func @_QPtest_kind2_convert(%arg0: !fir.box<!fir.array<?xi32>> {fir.bindc_n
// CHECK-NEXT: %[[V18:.*]] = arith.cmpi sge, %[[V17]], %[[V5]] : i32
// CHECK-NEXT: %[[V19:.*]] = fir.if %[[V18]] -> (i32) {
// CHECK-NEXT: %[[ISFIRST:.*]] = fir.load %[[V0]] : !fir.ref<i16>
// CHECK-NEXT: %[[V20:.*]]:3 = fir.box_dims %[[V2]]#0, %c0 : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index)
// CHECK-NEXT: %[[V21:.*]] = arith.subi %[[V20]]#0, %c1 : index
// CHECK-NEXT: %[[V22:.*]] = arith.addi %[[V15]], %[[V21]] : index
// CHECK-NEXT: %[[V23:.*]] = hlfir.designate %[[V2]]#0 (%[[V22]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V23:.*]] = hlfir.designate %[[V2]]#0 (%[[V15]]) : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK-NEXT: %[[V24:.*]] = fir.load %[[V23]] : !fir.ref<i32>
// CHECK-NEXT: %[[V25:.*]] = arith.cmpi slt, %[[V24]], %arg4 : i32
// CHECK-NEXT: %[[ISFIRSTL:.*]] = fir.convert %[[ISFIRST]] : (i16) -> i1
@ -291,10 +282,7 @@ func.func @_QPtest_float(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a
// CHECK-NEXT: %[[V17:.*]] = arith.cmpf oge, %[[V16]], %[[V4:.*]] : f32
// CHECK-NEXT: %[[V18:.*]] = fir.if %[[V17]] -> (f32) {
// CHECK-NEXT: %[[ISFIRST:.*]] = fir.load %[[V0:.*]] : !fir.ref<i32>
// CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %2#0, %c0 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
// CHECK-NEXT: %[[SUB:.*]] = arith.subi %[[DIMS]]#0, %c1 : index
// CHECK-NEXT: %[[ADD:.*]] = arith.addi %[[V14]], %[[SUB]] : index
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[ADD]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
// CHECK-NEXT: %[[V19:.*]] = hlfir.designate %[[V1]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
// CHECK-NEXT: %[[V20:.*]] = fir.load %[[V19]] : !fir.ref<f32>
// CHECK-NEXT: %[[NEW_MIN:.*]] = arith.cmpf olt, %[[V20]], %arg4 fastmath<contract> : f32
// CHECK-NEXT: %[[CONDRED:.*]] = arith.cmpf une, %arg4, %arg4 fastmath<contract> : f32