diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -289,6 +289,12 @@ llvm::SmallVector> genBounds(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value shape); +/// Generate lower bounds from a shape. If \p shape is null or is a fir.shape, +/// the returned vector will contain \p rank ones. +llvm::SmallVector genLowerbounds(mlir::Location loc, + fir::FirOpBuilder &builder, + mlir::Value shape, unsigned rank); + /// Compute fir.shape<> (no lower bounds) for an entity. mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder, Entity entity); diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -409,6 +409,20 @@ return result; } +llvm::SmallVector hlfir::genLowerbounds(mlir::Location loc, + fir::FirOpBuilder &builder, + mlir::Value shape, + unsigned rank) { + llvm::SmallVector lbounds; + if (shape) + lbounds = getExplicitLboundsFromShape(shape); + if (!lbounds.empty()) + return lbounds; + mlir::Value one = + builder.createIntegerConstant(loc, builder.getIndexType(), 1); + return llvm::SmallVector(rank, one); +} + static hlfir::Entity followShapeInducingSource(hlfir::Entity entity) { while (true) { if (auto reassoc = entity.getDefiningOp()) { diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp --- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp @@ -429,8 +429,19 @@ triples = genFullSliceTriples(builder, loc, baseEntity); sliceFields.push_back(fieldIndex); // Add indices in the field path for "array%array_comp(indices)" - // case. - sliceFields.append(subscripts.begin(), subscripts.end()); + // case. The indices of components provided to the sliceOp must + // be zero based (fir.slice has no knowledge of the component + // lower bounds). The component lower bounds are applied here. + if (!subscripts.empty()) { + llvm::SmallVector lbounds = hlfir::genLowerbounds( + loc, builder, designate.getComponentShape(), subscripts.size()); + for (auto [i, lb] : llvm::zip(subscripts, lbounds)) { + mlir::Value iIdx = builder.createConvert(loc, idxTy, i); + mlir::Value lbIdx = builder.createConvert(loc, idxTy, lb); + sliceFields.emplace_back( + builder.create(loc, iIdx, lbIdx)); + } + } } else { // Otherwise, this is an array section with triplets. auto undef = builder.create(loc, idxTy); diff --git a/flang/test/HLFIR/designate-codegen-component-refs.fir b/flang/test/HLFIR/designate-codegen-component-refs.fir --- a/flang/test/HLFIR/designate-codegen-component-refs.fir +++ b/flang/test/HLFIR/designate-codegen-component-refs.fir @@ -126,9 +126,47 @@ // CHECK: %[[VAL_9:.*]] = fir.field_index array_comp, !fir.type}> // CHECK: %[[VAL_10:.*]] = arith.constant 1 : index // CHECK: %[[VAL_11:.*]] = arith.constant 1 : index -// 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> +// CHECK: %[[ANOTHER_ONE:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_7B:.*]] = arith.subi %[[VAL_7]], %[[ANOTHER_ONE]] : index +// CHECK: %[[VAL_8B:.*]] = arith.subi %[[VAL_8]], %[[ANOTHER_ONE]] : index +// 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> // CHECK: %[[VAL_13:.*]] = fir.embox %[[VAL_3]](%[[VAL_2]]) {{\[}}%[[VAL_12]]] : (!fir.ref}>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + +func.func @test_array_array_comp_1_with_lbs(%arg0: !fir.ref}>>>) { + %c100 = arith.constant 100 : index + %0 = fir.shape %c100 : (index) -> !fir.shape<1> + %1:2 = hlfir.declare %arg0(%0) {uniq_name = "a"} : (!fir.ref}>>>, !fir.shape<1>) -> (!fir.ref}>>>, !fir.ref}>>>) + %c10 = arith.constant 10 : index + %c20 = arith.constant 20 : index + %c42 = arith.constant 42 : index + %c43 = arith.constant 43 : index + %5 = fir.shape_shift %c42, %c10, %c43, %c20 : (index, index, index, index) -> !fir.shapeshift<2> + %c45 = arith.constant 45 : index + %c47 = arith.constant 47 : index + %6 = hlfir.designate %1#0{"array_comp"} <%5> (%c45, %c47) shape %0 : (!fir.ref}>>>, !fir.shapeshift<2>, index, index, !fir.shape<1>) -> !fir.box> + return +} +// CHECK-LABEL: func.func @test_array_array_comp_1_with_lbs( +// CHECK: %[[VAL_1:.*]] = arith.constant 100 : index +// CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_3:.*]] = fir.declare %{{.*}}(%[[VAL_2]]) {uniq_name = "a"} : (!fir.ref}>>>, !fir.shape<1>) -> !fir.ref}>>> +// CHECK: %[[VAL_4:.*]] = arith.constant 10 : index +// CHECK: %[[VAL_5:.*]] = arith.constant 20 : index +// CHECK: %[[VAL_6:.*]] = arith.constant 42 : index +// CHECK: %[[VAL_7:.*]] = arith.constant 43 : index +// CHECK: %[[VAL_8:.*]] = fir.shape_shift %[[VAL_6]], %[[VAL_4]], %[[VAL_7]], %[[VAL_5]] : (index, index, index, index) -> !fir.shapeshift<2> +// CHECK: %[[VAL_9:.*]] = arith.constant 45 : index +// CHECK: %[[VAL_10:.*]] = arith.constant 47 : index +// CHECK: %[[VAL_11:.*]] = fir.field_index array_comp, !fir.type}> +// CHECK: %[[VAL_12:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_13:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_9]], %[[VAL_6]] : index +// CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_10]], %[[VAL_7]] : index +// 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> +// CHECK: %[[VAL_17:.*]] = fir.embox %[[VAL_3]](%[[VAL_2]]) {{\[}}%[[VAL_16]]] : (!fir.ref}>>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + + func.func @test_array_comp_slice(%arg0: !fir.ref}>>) { %0:2 = hlfir.declare %arg0 {uniq_name = "ga"} : (!fir.ref}>>) -> (!fir.ref}>>, !fir.ref}>>) %c10 = arith.constant 10 : index