Skip to content

Commit 752bd78

Browse files
committed
[flang][hlfir] Apply component lower bounds in hlfir.designate codegen
The array component indices in the "path" of a fir.slice are zero based because FIR does not know about the component lower bounds. When lowering hlfir.designate to FIR for `array%x(i, j)`, convert `i` and `j` to zero based indices before generating the fir.slice. Differential Revision: https://reviews.llvm.org/D148627
1 parent 3f4055d commit 752bd78

File tree

4 files changed

+72
-3
lines changed

4 files changed

+72
-3
lines changed

flang/include/flang/Optimizer/Builder/HLFIRTools.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ genBounds(mlir::Location loc, fir::FirOpBuilder &builder, Entity entity);
289289
llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
290290
genBounds(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value shape);
291291

292+
/// Generate lower bounds from a shape. If \p shape is null or is a fir.shape,
293+
/// the returned vector will contain \p rank ones.
294+
llvm::SmallVector<mlir::Value> genLowerbounds(mlir::Location loc,
295+
fir::FirOpBuilder &builder,
296+
mlir::Value shape, unsigned rank);
297+
292298
/// Compute fir.shape<> (no lower bounds) for an entity.
293299
mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder,
294300
Entity entity);

flang/lib/Optimizer/Builder/HLFIRTools.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,20 @@ hlfir::genBounds(mlir::Location loc, fir::FirOpBuilder &builder,
409409
return result;
410410
}
411411

412+
llvm::SmallVector<mlir::Value> hlfir::genLowerbounds(mlir::Location loc,
413+
fir::FirOpBuilder &builder,
414+
mlir::Value shape,
415+
unsigned rank) {
416+
llvm::SmallVector<mlir::Value> lbounds;
417+
if (shape)
418+
lbounds = getExplicitLboundsFromShape(shape);
419+
if (!lbounds.empty())
420+
return lbounds;
421+
mlir::Value one =
422+
builder.createIntegerConstant(loc, builder.getIndexType(), 1);
423+
return llvm::SmallVector<mlir::Value>(rank, one);
424+
}
425+
412426
static hlfir::Entity followShapeInducingSource(hlfir::Entity entity) {
413427
while (true) {
414428
if (auto reassoc = entity.getDefiningOp<hlfir::NoReassocOp>()) {

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,19 @@ class DesignateOpConversion
429429
triples = genFullSliceTriples(builder, loc, baseEntity);
430430
sliceFields.push_back(fieldIndex);
431431
// Add indices in the field path for "array%array_comp(indices)"
432-
// case.
433-
sliceFields.append(subscripts.begin(), subscripts.end());
432+
// case. The indices of components provided to the sliceOp must
433+
// be zero based (fir.slice has no knowledge of the component
434+
// lower bounds). The component lower bounds are applied here.
435+
if (!subscripts.empty()) {
436+
llvm::SmallVector<mlir::Value> lbounds = hlfir::genLowerbounds(
437+
loc, builder, designate.getComponentShape(), subscripts.size());
438+
for (auto [i, lb] : llvm::zip(subscripts, lbounds)) {
439+
mlir::Value iIdx = builder.createConvert(loc, idxTy, i);
440+
mlir::Value lbIdx = builder.createConvert(loc, idxTy, lb);
441+
sliceFields.emplace_back(
442+
builder.create<mlir::arith::SubIOp>(loc, iIdx, lbIdx));
443+
}
444+
}
434445
} else {
435446
// Otherwise, this is an array section with triplets.
436447
auto undef = builder.create<fir::UndefOp>(loc, idxTy);

flang/test/HLFIR/designate-codegen-component-refs.fir

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,47 @@ func.func @test_array_array_comp_1(%arg0: !fir.ref<!fir.array<100x!fir.type<t_ar
126126
// CHECK: %[[VAL_9:.*]] = fir.field_index array_comp, !fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>
127127
// CHECK: %[[VAL_10:.*]] = arith.constant 1 : index
128128
// CHECK: %[[VAL_11:.*]] = arith.constant 1 : index
129-
// CHECK: %[[VAL_12:.*]] = fir.slice %[[VAL_11]], %[[VAL_1]], %[[VAL_10]] path %[[VAL_9]], %[[VAL_7]], %[[VAL_8]] : (index, index, index, !fir.field, index, index) -> !fir.slice<1>
129+
// CHECK: %[[ANOTHER_ONE:.*]] = arith.constant 1 : index
130+
// CHECK: %[[VAL_7B:.*]] = arith.subi %[[VAL_7]], %[[ANOTHER_ONE]] : index
131+
// CHECK: %[[VAL_8B:.*]] = arith.subi %[[VAL_8]], %[[ANOTHER_ONE]] : index
132+
// CHECK: %[[VAL_12:.*]] = fir.slice %[[VAL_11]], %[[VAL_1]], %[[VAL_10]] path %[[VAL_9]], %[[VAL_7B]], %[[VAL_8B]] : (index, index, index, !fir.field, index, index) -> !fir.slice<1>
130133
// CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_3]](%[[VAL_2]]) {{\[}}%[[VAL_12]]] : (!fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<100xf32>>
131134

135+
136+
func.func @test_array_array_comp_1_with_lbs(%arg0: !fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>) {
137+
%c100 = arith.constant 100 : index
138+
%0 = fir.shape %c100 : (index) -> !fir.shape<1>
139+
%1:2 = hlfir.declare %arg0(%0) {uniq_name = "a"} : (!fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>, !fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>)
140+
%c10 = arith.constant 10 : index
141+
%c20 = arith.constant 20 : index
142+
%c42 = arith.constant 42 : index
143+
%c43 = arith.constant 43 : index
144+
%5 = fir.shape_shift %c42, %c10, %c43, %c20 : (index, index, index, index) -> !fir.shapeshift<2>
145+
%c45 = arith.constant 45 : index
146+
%c47 = arith.constant 47 : index
147+
%6 = hlfir.designate %1#0{"array_comp"} <%5> (%c45, %c47) shape %0 : (!fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>, !fir.shapeshift<2>, index, index, !fir.shape<1>) -> !fir.box<!fir.array<100xf32>>
148+
return
149+
}
150+
// CHECK-LABEL: func.func @test_array_array_comp_1_with_lbs(
151+
// CHECK: %[[VAL_1:.*]] = arith.constant 100 : index
152+
// CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
153+
// CHECK: %[[VAL_3:.*]] = fir.declare %{{.*}}(%[[VAL_2]]) {uniq_name = "a"} : (!fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>, !fir.shape<1>) -> !fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>
154+
// CHECK: %[[VAL_4:.*]] = arith.constant 10 : index
155+
// CHECK: %[[VAL_5:.*]] = arith.constant 20 : index
156+
// CHECK: %[[VAL_6:.*]] = arith.constant 42 : index
157+
// CHECK: %[[VAL_7:.*]] = arith.constant 43 : index
158+
// CHECK: %[[VAL_8:.*]] = fir.shape_shift %[[VAL_6]], %[[VAL_4]], %[[VAL_7]], %[[VAL_5]] : (index, index, index, index) -> !fir.shapeshift<2>
159+
// CHECK: %[[VAL_9:.*]] = arith.constant 45 : index
160+
// CHECK: %[[VAL_10:.*]] = arith.constant 47 : index
161+
// CHECK: %[[VAL_11:.*]] = fir.field_index array_comp, !fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>
162+
// CHECK: %[[VAL_12:.*]] = arith.constant 1 : index
163+
// CHECK: %[[VAL_13:.*]] = arith.constant 1 : index
164+
// CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_9]], %[[VAL_6]] : index
165+
// CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_10]], %[[VAL_7]] : index
166+
// CHECK: %[[VAL_16:.*]] = fir.slice %[[VAL_13]], %[[VAL_1]], %[[VAL_12]] path %[[VAL_11]], %[[VAL_14]], %[[VAL_15]] : (index, index, index, !fir.field, index, index) -> !fir.slice<1>
167+
// CHECK: %[[VAL_17:.*]] = fir.embox %[[VAL_3]](%[[VAL_2]]) {{\[}}%[[VAL_16]]] : (!fir.ref<!fir.array<100x!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<100xf32>>
168+
169+
132170
func.func @test_array_comp_slice(%arg0: !fir.ref<!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>) {
133171
%0:2 = hlfir.declare %arg0 {uniq_name = "ga"} : (!fir.ref<!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>) -> (!fir.ref<!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>, !fir.ref<!fir.type<t_array{scalar_i:i32,array_comp:!fir.array<10x20xf32>}>>)
134172
%c10 = arith.constant 10 : index

0 commit comments

Comments
 (0)