Skip to content

Commit 3aad7d7

Browse files
authored
[flang] Fixed designator codegen for contiguous boxes. (#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.
1 parent 6dc6ca3 commit 3aad7d7

File tree

3 files changed

+99
-6
lines changed

3 files changed

+99
-6
lines changed

flang/lib/Optimizer/Builder/HLFIRTools.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ getExplicitExtents(fir::FortranVariableOpInterface var,
7070
return {};
7171
}
7272

73-
// Return explicit lower bounds. For pointers and allocatables, this will not
74-
// read the lower bounds and instead return an empty vector.
73+
// Return explicit lower bounds from a shape result.
74+
// Only fir.shape, fir.shift and fir.shape_shift are currently
75+
// supported as shape.
7576
static llvm::SmallVector<mlir::Value>
7677
getExplicitLboundsFromShape(mlir::Value shape) {
7778
llvm::SmallVector<mlir::Value> result;
@@ -89,6 +90,9 @@ getExplicitLboundsFromShape(mlir::Value shape) {
8990
}
9091
return result;
9192
}
93+
94+
// Return explicit lower bounds. For pointers and allocatables, this will not
95+
// read the lower bounds and instead return an empty vector.
9296
static llvm::SmallVector<mlir::Value>
9397
getExplicitLbounds(fir::FortranVariableOpInterface var) {
9498
if (mlir::Value shape = var.getShape())
@@ -753,9 +757,30 @@ std::pair<mlir::Value, mlir::Value> hlfir::genVariableFirBaseShapeAndParams(
753757
}
754758
if (entity.isScalar())
755759
return {fir::getBase(exv), mlir::Value{}};
756-
if (auto variableInterface = entity.getIfVariableInterface())
757-
return {fir::getBase(exv),
758-
asEmboxShape(loc, builder, exv, variableInterface.getShape())};
760+
761+
// Contiguous variables that are represented with a box
762+
// may require the shape to be extracted from the box (i.e. evx),
763+
// because they itself may not have shape specified.
764+
// This happens during late propagationg of contiguous
765+
// attribute, e.g.:
766+
// %9:2 = hlfir.declare %6
767+
// {fortran_attrs = #fir.var_attrs<contiguous>} :
768+
// (!fir.box<!fir.array<?x?x...>>) ->
769+
// (!fir.box<!fir.array<?x?x...>>, !fir.box<!fir.array<?x?x...>>)
770+
// The extended value is an ArrayBoxValue with base being
771+
// the raw address of the array.
772+
if (auto variableInterface = entity.getIfVariableInterface()) {
773+
mlir::Value shape = variableInterface.getShape();
774+
if (mlir::isa<fir::BaseBoxType>(fir::getBase(exv).getType()) ||
775+
!mlir::isa<fir::BaseBoxType>(entity.getType()) ||
776+
// Still use the variable's shape if it is present.
777+
// If it only specifies a shift, then we have to create
778+
// a shape from the exv.
779+
(shape && (shape.getDefiningOp<fir::ShapeShiftOp>() ||
780+
shape.getDefiningOp<fir::ShapeOp>())))
781+
return {fir::getBase(exv),
782+
asEmboxShape(loc, builder, exv, variableInterface.getShape())};
783+
}
759784
return {fir::getBase(exv), builder.createShape(loc, exv)};
760785
}
761786

flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,10 +414,11 @@ class DesignateOpConversion
414414
auto attrs = designate.getIsTripletAttr();
415415
for (auto isTriplet : attrs.asArrayRef()) {
416416
// Coordinate of the first element are the index and triplets lower
417-
// bounds
417+
// bounds.
418418
firstElementIndices.push_back(indices[i]);
419419
i = i + (isTriplet ? 3 : 1);
420420
}
421+
421422
mlir::Type originalDesignateType = designate.getResult().getType();
422423
const bool isVolatile = fir::isa_volatile_type(originalDesignateType);
423424
mlir::Type arrayCoorType = fir::ReferenceType::get(baseEleTy, isVolatile);

flang/test/HLFIR/designate-codegen.fir

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,70 @@ func.func @test_polymorphic_array_elt(%arg0: !fir.class<!fir.array<?x!fir.type<_
213213
// 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>>
214214
// CHECK: return
215215
// CHECK: }
216+
217+
// Test proper generation of fir.array_coor for contiguous box with default lbounds.
218+
func.func @_QPtest_contiguous_derived_default(%arg0: !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>> {fir.bindc_name = "d1", fir.contiguous, fir.optional}) {
219+
%c1 = arith.constant 1 : index
220+
%c16_i32 = arith.constant 16 : i32
221+
%0 = fir.dummy_scope : !fir.dscope
222+
%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>>>)
223+
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]
224+
^bb1: // pred: ^bb0
225+
%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}>>>
226+
%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}>>>)
227+
%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}>>
228+
%5 = hlfir.designate %4{"i"} : (!fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>) -> !fir.ref<i32>
229+
hlfir.assign %c16_i32 to %5 : i32, !fir.ref<i32>
230+
cf.br ^bb3
231+
^bb2: // pred: ^bb0
232+
%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>>>)
233+
cf.br ^bb3
234+
^bb3: // 2 preds: ^bb1, ^bb2
235+
return
236+
}
237+
// CHECK-LABEL: func.func @_QPtest_contiguous_derived_default(
238+
// CHECK: %[[VAL_0:.*]] = arith.constant 1 : index
239+
// 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}>>>
240+
// 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}>>>
241+
// 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}>>>
242+
// CHECK: %[[VAL_12:.*]] = arith.constant 0 : index
243+
// 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)
244+
// CHECK: %[[VAL_14:.*]] = arith.constant 1 : index
245+
// 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)
246+
// CHECK: %[[VAL_16:.*]] = fir.shape %[[VAL_13]]#1, %[[VAL_15]]#1 : (index, index) -> !fir.shape<2>
247+
// 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}>>
248+
249+
// Test proper generation of fir.array_coor for contiguous box with non-default lbounds.
250+
func.func @_QPtest_contiguous_derived_lbounds(%arg0: !fir.class<!fir.array<?x?x!fir.type<_QMtypesTt1>>> {fir.bindc_name = "d1", fir.contiguous}) {
251+
%c3 = arith.constant 3 : index
252+
%c1 = arith.constant 1 : index
253+
%c16_i32 = arith.constant 16 : i32
254+
%0 = fir.dummy_scope : !fir.dscope
255+
%1 = fir.shift %c1, %c3 : (index, index) -> !fir.shift<2>
256+
%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>>>)
257+
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]
258+
^bb1: // pred: ^bb0
259+
%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}>>>
260+
%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}>>>)
261+
%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}>>
262+
%6 = hlfir.designate %5{"i"} : (!fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>) -> !fir.ref<i32>
263+
hlfir.assign %c16_i32 to %6 : i32, !fir.ref<i32>
264+
cf.br ^bb3
265+
^bb2: // pred: ^bb0
266+
%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>>>)
267+
cf.br ^bb3
268+
^bb3: // 2 preds: ^bb1, ^bb2
269+
return
270+
}
271+
// CHECK-LABEL: func.func @_QPtest_contiguous_derived_lbounds(
272+
// CHECK: %[[VAL_0:.*]] = arith.constant 3 : index
273+
// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
274+
// 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}>>>
275+
// 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}>>>
276+
// 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}>>>
277+
// CHECK: %[[VAL_11:.*]] = arith.constant 0 : index
278+
// 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)
279+
// CHECK: %[[VAL_13:.*]] = arith.constant 1 : index
280+
// 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)
281+
// CHECK: %[[VAL_15:.*]] = fir.shape_shift %[[VAL_1]], %[[VAL_12]]#1, %[[VAL_0]], %[[VAL_14]]#1 : (index, index, index, index) -> !fir.shapeshift<2>
282+
// CHECK: %[[VAL_16:.*]] = fir.array_coor %[[VAL_10]](%[[VAL_15]]) %[[VAL_1]], %[[VAL_0]] : (!fir.ref<!fir.array<?x?x!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>>, !fir.shapeshift<2>, index, index) -> !fir.ref<!fir.type<_QMtypesTt2{t1:!fir.type<_QMtypesTt1>,i:i32}>>

0 commit comments

Comments
 (0)