-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[flang] Fixed designator codegen for contiguous boxes. #139003
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
Conversation
Contiguous variables represented with a box do not have explicit shape, but it looks like the base/shape computation was assuming that. This caused generation of raw address fir.array_coor without the shape. This patch is needed to fix failures hapenning with llvm#138797.
@llvm/pr-subscribers-flang-fir-hlfir Author: Slava Zakharin (vzakhari) ChangesContiguous variables represented with a box do not have Full diff: https://github.com/llvm/llvm-project/pull/139003.diff 4 Files Affected:
diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index ac80873dc374f..bcba38ed8bd5d 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -533,6 +533,12 @@ Entity gen1DSection(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::ArrayRef<mlir::Value> extents,
mlir::ValueRange oneBasedIndices,
mlir::ArrayRef<mlir::Value> typeParams);
+
+/// Return explicit lower bounds from a fir.shape result.
+/// Only fir.shape, fir.shift and fir.shape_shift are currently
+/// supported as \p shape.
+llvm::SmallVector<mlir::Value> getExplicitLboundsFromShape(mlir::Value shape);
+
} // namespace hlfir
#endif // FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 51ea7305d3d26..752dc0cf86414 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -70,10 +70,8 @@ getExplicitExtents(fir::FortranVariableOpInterface var,
return {};
}
-// Return explicit lower bounds. For pointers and allocatables, this will not
-// read the lower bounds and instead return an empty vector.
-static llvm::SmallVector<mlir::Value>
-getExplicitLboundsFromShape(mlir::Value shape) {
+llvm::SmallVector<mlir::Value>
+hlfir::getExplicitLboundsFromShape(mlir::Value shape) {
llvm::SmallVector<mlir::Value> result;
auto *shapeOp = shape.getDefiningOp();
if (auto s = mlir::dyn_cast_or_null<fir::ShapeOp>(shapeOp)) {
@@ -89,10 +87,13 @@ getExplicitLboundsFromShape(mlir::Value shape) {
}
return result;
}
+
+// Return explicit lower bounds. For pointers and allocatables, this will not
+// read the lower bounds and instead return an empty vector.
static llvm::SmallVector<mlir::Value>
getExplicitLbounds(fir::FortranVariableOpInterface var) {
if (mlir::Value shape = var.getShape())
- return getExplicitLboundsFromShape(shape);
+ return hlfir::getExplicitLboundsFromShape(shape);
return {};
}
@@ -753,9 +754,24 @@ std::pair<mlir::Value, mlir::Value> hlfir::genVariableFirBaseShapeAndParams(
}
if (entity.isScalar())
return {fir::getBase(exv), mlir::Value{}};
+
+ // Contiguous variables that are represented with a box
+ // may require the shape to be extracted from the box (i.e. evx),
+ // because they itself may not have shape specified.
+ // This happens during late propagationg of contiguous
+ // attribute, e.g.:
+ // %9:2 = hlfir.declare %6
+ // {fortran_attrs = #fir.var_attrs<contiguous>} :
+ // (!fir.box<!fir.array<?x?x...>>) ->
+ // (!fir.box<!fir.array<?x?x...>>, !fir.box<!fir.array<?x?x...>>)
+ // The extended value is an ArrayBoxValue with base being
+ // the raw address of the array.
if (auto variableInterface = entity.getIfVariableInterface())
- return {fir::getBase(exv),
- asEmboxShape(loc, builder, exv, variableInterface.getShape())};
+ if (mlir::isa<fir::BaseBoxType>(fir::getBase(exv).getType()) ||
+ !mlir::isa<fir::BaseBoxType>(entity.getType()) ||
+ variableInterface.getShape())
+ return {fir::getBase(exv),
+ asEmboxShape(loc, builder, exv, variableInterface.getShape())};
return {fir::getBase(exv), builder.createShape(loc, exv)};
}
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index 8721a895b5e05..495f11a365185 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -412,12 +412,44 @@ class DesignateOpConversion
auto indices = designate.getIndices();
int i = 0;
auto attrs = designate.getIsTripletAttr();
+
+ // If the shape specifies a shift and the base is not a box,
+ // then we have to subtract the lower bounds, as long as
+ // fir.array_coor does not support non-default lower bounds
+ // for non-box accesses.
+ llvm::SmallVector<mlir::Value> lbounds;
+ if (shape && !mlir::isa<fir::BaseBoxType>(base.getType()))
+ lbounds = hlfir::getExplicitLboundsFromShape(shape);
+ std::size_t lboundIdx = 0;
for (auto isTriplet : attrs.asArrayRef()) {
// Coordinate of the first element are the index and triplets lower
- // bounds
- firstElementIndices.push_back(indices[i]);
+ // bounds.
+ mlir::Value index = indices[i];
+ if (!lbounds.empty()) {
+ assert(lboundIdx < lbounds.size() && "missing lbound");
+ mlir::Type indexType = builder.getIndexType();
+ mlir::Value one = builder.createIntegerConstant(loc, indexType, 1);
+ mlir::Value orig = builder.createConvert(loc, indexType, index);
+ mlir::Value lb =
+ builder.createConvert(loc, indexType, lbounds[lboundIdx]);
+ index = builder.create<mlir::arith::SubIOp>(loc, orig, lb);
+ index = builder.create<mlir::arith::AddIOp>(loc, index, one);
+ ++lboundIdx;
+ }
+ firstElementIndices.push_back(index);
i = i + (isTriplet ? 3 : 1);
}
+
+ // Remove the shift from the shape, if needed.
+ if (!lbounds.empty()) {
+ mlir::Operation *op = shape.getDefiningOp();
+ if (mlir::isa<fir::ShiftOp>(op))
+ shape = nullptr;
+ else if (auto shiftOp = mlir::dyn_cast<fir::ShapeShiftOp>(op))
+ shape = builder.create<fir::ShapeOp>(loc, shiftOp.getExtents());
+ else
+ TODO(loc, "read fir.shape to get lower bounds");
+ }
mlir::Type originalDesignateType = designate.getResult().getType();
const bool isVolatile = fir::isa_volatile_type(originalDesignateType);
mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy, isVolatile);
diff --git a/flang/test/HLFIR/designate-codegen.fir b/flang/test/HLFIR/designate-codegen.fir
index da0a1f82b516e..d3e264941264f 100644
--- a/flang/test/HLFIR/designate-codegen.fir
+++ b/flang/test/HLFIR/designate-codegen.fir
@@ -213,3 +213,75 @@ func.func @test_polymorphic_array_elt(%arg0: !fir.class<!fir.array<?x!fir.type<_
// CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]] source_box %[[VAL_2]] : (!fir.ref<!fir.type<_QMtypesTt1>>, !fir.class<!fir.array<?x!fir.type<_QMtypesTt1>>>) -> !fir.class<!fir.type<_QMtypesTt1>>
// CHECK: return
// CHECK: }
+
+// Test proper generation of fir.array_coor for contiguous box with default lbounds.
+func.func @_QPtest_contiguous_derived_default(%arg0: !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>> {fir.bindc_name = "d1", fir.contiguous, fir.optional}) {
+ %c1 = arith.constant 1 : index
+ %c16_i32 = arith.constant 16 : i32
+ %0 = fir.dummy_scope : !fir.dscope
+ %1:2 = hlfir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<contiguous, optional>, uniq_name = "_QFtest_contiguous_derived_defaultEd1"} : (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.dscope) -> (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>)
+ fir.select_type %1#1 : !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>> [#fir.type_is<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>, ^bb1, unit, ^bb2]
+^bb1: // pred: ^bb0
+ %2 = fir.convert %1#1 : (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>) -> !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+ %3:2 = hlfir.declare %2 {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_defaultEd1"} : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>) -> (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>)
+ %4 = hlfir.designate %3#0 (%c1, %c1) : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index, index) -> !fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>
+ %5 = hlfir.designate %4{"i"} : (!fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>) -> !fir.ref<i32>
+ hlfir.assign %c16_i32 to %5 : i32, !fir.ref<i32>
+ cf.br ^bb3
+^bb2: // pred: ^bb0
+ %6:2 = hlfir.declare %1#1 {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_defaultEd1"} : (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>) -> (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>)
+ cf.br ^bb3
+^bb3: // 2 preds: ^bb1, ^bb2
+ return
+}
+// CHECK-LABEL: func.func @_QPtest_contiguous_derived_default(
+// CHECK: %[[VAL_0:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_9:.*]] = fir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_defaultEd1"} : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>) -> !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+// CHECK: %[[VAL_10:.*]] = fir.rebox %[[VAL_9]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>) -> !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+// CHECK: %[[VAL_11:.*]] = fir.box_addr %[[VAL_10]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>) -> !fir.ref<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+// CHECK: %[[VAL_12:.*]] = arith.constant 0 : index
+// CHECK: %[[VAL_13:.*]]:3 = fir.box_dims %[[VAL_10]], %[[VAL_12]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index) -> (index, index, index)
+// CHECK: %[[VAL_14:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_15:.*]]:3 = fir.box_dims %[[VAL_10]], %[[VAL_14]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index) -> (index, index, index)
+// CHECK: %[[VAL_16:.*]] = fir.shape %[[VAL_13]]#1, %[[VAL_15]]#1 : (index, index) -> !fir.shape<2>
+// CHECK: %[[VAL_17:.*]] = fir.array_coor %[[VAL_11]](%[[VAL_16]]) %[[VAL_0]], %[[VAL_0]] : (!fir.ref<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.shape<2>, index, index) -> !fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>
+
+// Test proper generation of fir.array_coor for contiguous box with non-default lbounds.
+func.func @_QPtest_contiguous_derived_lbounds(%arg0: !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>> {fir.bindc_name = "d1", fir.contiguous}) {
+ %c3 = arith.constant 3 : index
+ %c1 = arith.constant 1 : index
+ %c16_i32 = arith.constant 16 : i32
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.shift %c1, %c3 : (index, index) -> !fir.shift<2>
+ %2:2 = hlfir.declare %arg0(%1) dummy_scope %0 {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_lboundsEd1"} : (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.shift<2>, !fir.dscope) -> (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>)
+ fir.select_type %2#1 : !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>> [#fir.type_is<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>, ^bb1, unit, ^bb2]
+^bb1: // pred: ^bb0
+ %3 = fir.convert %2#1 : (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>) -> !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+ %4:2 = hlfir.declare %3(%1) {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_lboundsEd1"} : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.shift<2>) -> (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>)
+ %5 = hlfir.designate %4#0 (%c1, %c3) : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index, index) -> !fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>
+ %6 = hlfir.designate %5{"i"} : (!fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>) -> !fir.ref<i32>
+ hlfir.assign %c16_i32 to %6 : i32, !fir.ref<i32>
+ cf.br ^bb3
+^bb2: // pred: ^bb0
+ %7:2 = hlfir.declare %2#1(%1) {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_lboundsEd1"} : (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.shift<2>) -> (!fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>, !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>>)
+ cf.br ^bb3
+^bb3: // 2 preds: ^bb1, ^bb2
+ return
+}
+// CHECK-LABEL: func.func @_QPtest_contiguous_derived_lbounds(
+// CHECK: %[[VAL_0:.*]] = arith.constant 3 : index
+// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_8:.*]] = fir.declare %{{.*}}(%[[VAL_4:.*]]) {fortran_attrs = #fir.var_attrs<contiguous>, uniq_name = "_QFtest_contiguous_derived_lboundsEd1"} : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+// CHECK: %[[VAL_9:.*]] = fir.rebox %[[VAL_8]](%[[VAL_4]]) : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+// CHECK: %[[VAL_10:.*]] = fir.box_addr %[[VAL_9]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>) -> !fir.ref<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>
+// CHECK: %[[VAL_11:.*]] = arith.constant 0 : index
+// CHECK: %[[VAL_12:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_11]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index) -> (index, index, index)
+// CHECK: %[[VAL_13:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_14:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_13]] : (!fir.box<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index) -> (index, index, index)
+// CHECK: %[[VAL_15:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_16:.*]] = arith.subi %[[VAL_1]], %[[VAL_1]] : index
+// CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_16]], %[[VAL_15]] : index
+// CHECK: %[[VAL_18:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_19:.*]] = arith.subi %[[VAL_0]], %[[VAL_0]] : index
+// CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_19]], %[[VAL_18]] : index
+// CHECK: %[[VAL_21:.*]] = fir.array_coor %[[VAL_10]] %[[VAL_17]], %[[VAL_20]] : (!fir.ref<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index, index) -> !fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>
|
asEmboxShape(loc, builder, exv, variableInterface.getShape())}; | ||
if (mlir::isa<fir::BaseBoxType>(fir::getBase(exv).getType()) || | ||
!mlir::isa<fir::BaseBoxType>(entity.getType()) || | ||
variableInterface.getShape()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the CONTIGUOUS variable has custom lower bounds, I think there will be a fir.shift
returned by variableInterface.getShape()
instead of the needed fir.shift_shape.
// CHECK: %[[VAL_18:.*]] = arith.constant 1 : index | ||
// CHECK: %[[VAL_19:.*]] = arith.subi %[[VAL_0]], %[[VAL_0]] : index | ||
// CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_19]], %[[VAL_18]] : index | ||
// CHECK: %[[VAL_21:.*]] = fir.array_coor %[[VAL_10]] %[[VAL_17]], %[[VAL_20]] : (!fir.ref<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, index, index) -> !fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this possible that this fir.array_coor has no shape argument? How can codegen compute the stride for the second dimension?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this! It should not work, so I missed something.
// fir.array_coor does not support non-default lower bounds | ||
// for non-box accesses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure I get it. Is fir.array_coor not honoring fir.shape_shift? That seems like a big bug in its codegen.
I think this may be related to my comment in the HLFIRTools.cpp helper though, genVariableFirBaseShapeAndParams should not return a fir.shift it the exv is not a box (it should be a fir.shape_shift).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hitting "shift can only be provided with fir.box memref" error in fir::ArrayCoorOp::verify
, but I now see a comment there saying that the codegen does support it:
// TODO: it looks like PreCGRewrite and CodeGen can support
// fir.shift with plain array reference, so we may consider
// removing this check.
if (!mlir::isa<fir::BaseBoxType>(getMemref().getType()))
return emitOpError("shift can only be provided with fir.box memref");
I will do more investigation.
in ConvertToFIR.
Thank you for the comments, Jean! I uploaded an update. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the update and the fix, LGTM!
This change allows marking more designators producing an opaque box with 'contiguous' attribute, e.g. like in test1 case in flang/test/HLFIR/propagate-contiguous-attribute.fir. This would make isSimplyContiguous() return true for such designators allowing merging hlfir.eval_in_mem with hlfir.assign where the LHS is a contiguous array section. Depends on #139003
Contiguous variables represented with a box do not have
explicit shape, but it looks like the base/shape computation
was assuming that. This caused generation of raw address
fir.array_coor without the shape. This patch is needed
to fix failures hapenning with #138797.