diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index 29cccbd1bfe5a..37b926e2f23f2 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -14,11 +14,12 @@ #include "ClauseFinder.h" #include "flang/Evaluate/fold.h" -#include "flang/Lower/OpenMP/Clauses.h" #include #include #include +#include #include +#include #include #include #include @@ -180,16 +181,11 @@ static void generateArrayIndices(lower::AbstractConverter &converter, for (auto v : arr->subscript()) { if (std::holds_alternative(v.u)) TODO(clauseLocation, "Triplet indexing in map clause is unsupported"); - auto expr = std::get(v.u); mlir::Value subscript = fir::getBase(converter.genExprValue(toEvExpr(expr.value()), stmtCtx)); - mlir::Value one = firOpBuilder.createIntegerConstant( - clauseLocation, firOpBuilder.getIndexType(), 1); - subscript = firOpBuilder.createConvert( - clauseLocation, firOpBuilder.getIndexType(), subscript); - indices.push_back(mlir::arith::SubIOp::create(firOpBuilder, clauseLocation, - subscript, one)); + indices.push_back(firOpBuilder.createConvert( + clauseLocation, firOpBuilder.getIndexType(), subscript)); } } @@ -322,10 +318,42 @@ mlir::Value createParentSymAndGenIntermediateMaps( subscriptIndices, objectList[i]); assert(!subscriptIndices.empty() && "missing expected indices for map clause"); - curValue = fir::CoordinateOp::create( - firOpBuilder, clauseLocation, - firOpBuilder.getRefType(arrType.getEleTy()), curValue, - subscriptIndices); + if (auto boxTy = llvm::dyn_cast(curValue.getType())) { + // To accommodate indexing into box types of all dimensions including + // negative dimensions we have to take into consideration the lower + // bounds and extents of the data (stored in the box) and convey it + // to the ArrayCoorOp so that it can appropriately access the element + // utilising the subscript we provide and the runtime sizes stored in + // the Box. To do so we need to generate a ShapeShiftOp which combines + // both the lb (ShiftOp) and extent (ShapeOp) of the Box, giving the + // ArrayCoorOp the spatial information it needs to calculate the + // underlying address. + mlir::Value shapeShift = Fortran::lower::getShapeShift( + firOpBuilder, clauseLocation, curValue); + auto addrOp = + fir::BoxAddrOp::create(firOpBuilder, clauseLocation, curValue); + curValue = fir::ArrayCoorOp::create( + firOpBuilder, clauseLocation, + firOpBuilder.getRefType(arrType.getEleTy()), addrOp, shapeShift, + /*slice=*/mlir::Value{}, subscriptIndices, + /*typeparms=*/mlir::ValueRange{}); + } else { + // We're required to negate by one in the non-Box case as I believe + // we do not have the shape generated from the dimensions to help + // adjust the indexing. + // TODO/FIXME: This may need adjusted to support bounds of unusual + // dimensions, if that's the case then it is likely best to fold this + // branch into the above. + mlir::Value one = firOpBuilder.createIntegerConstant( + clauseLocation, firOpBuilder.getIndexType(), 1); + for (auto &v : subscriptIndices) + v = mlir::arith::SubIOp::create(firOpBuilder, clauseLocation, v, + one); + curValue = fir::CoordinateOp::create( + firOpBuilder, clauseLocation, + firOpBuilder.getRefType(arrType.getEleTy()), curValue, + subscriptIndices); + } } } @@ -415,7 +443,6 @@ mlir::Value createParentSymAndGenIntermediateMaps( currentIndicesIdx++; } } - return curValue; } diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 index 665be5a8db4d4..44a049f5ac510 100644 --- a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 +++ b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 @@ -785,15 +785,20 @@ end subroutine mapType_common_block_members !CHECK: %[[BOUNDS_CALC:.*]] = sub i64 %[[BOUNDS_LD_2]], 1 !CHECK: %[[OFF_PTR_CALC_0:.*]] = sub i64 %[[BOUNDS_LD]], 1 !CHECK: %[[OFF_PTR_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[OFF_PTR_1]], i32 0, i32 0 +!CHECK: %[[GEP_LB:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 7, i64 0, i32 0 +!CHECK: %[[LOAD_LB:.*]] = load i64, ptr %[[GEP_LB]], align 8 +!CHECK: %[[GEP_UB:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[LOAD_UB:.*]] = load i64, ptr %[[GEP_UB]], align 8 !CHECK: %[[GEP_DESC_PTR:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 0 -!CHECK: %[[LOAD_DESC_PTR:.*]] = load ptr, ptr %[[GEP_DESC_PTR]], align 8 -!CHECK: %[[SZ_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 7, i32 0, i32 2 -!CHECK: %[[SZ_CALC_2:.*]] = load i64, ptr %[[SZ_CALC_1]], align 8 -!CHECK: %[[SZ_CALC_3:.*]] = mul nsw i64 1, %[[SZ_CALC_2]] -!CHECK: %[[SZ_CALC_4:.*]] = add nsw i64 %[[SZ_CALC_3]], 0 -!CHECK: %[[SZ_CALC_5:.*]] = getelementptr i8, ptr %[[LOAD_DESC_PTR]], i64 %[[SZ_CALC_4]] -!CHECK: %[[SZ_CALC_6:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_5]], i32 0, i32 2 -!CHECK: %[[OFF_PTR_4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[SZ_CALC_6]], i32 0, i32 0 +!CHECK: %[[SZ_CALC_1:.*]] = load ptr, ptr %[[GEP_DESC_PTR]], align 8 +!CHECK: %[[SZ_CALC_2:.*]] = sub nsw i64 2, %[[LOAD_LB]] +!CHECK: %[[SZ_CALC_3:.*]] = mul nsw i64 %[[SZ_CALC_2]], 1 +!CHECK: %[[SZ_CALC_4:.*]] = mul nsw i64 %[[SZ_CALC_3]], 1 +!CHECK: %[[SZ_CALC_5:.*]] = add nsw i64 %[[SZ_CALC_4]], 0 +!CHECK: %[[SZ_CALC_6:.*]] = mul nsw i64 1, %[[LOAD_UB]] +!CHECK: %[[SZ_CALC_7:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_1]], i64 %[[SZ_CALC_5]] +!CHECK: %[[SZ_CALC_8:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_7]], i32 0, i32 2 +!CHECK: %[[OFF_PTR_4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[SZ_CALC_8]], i32 0, i32 0 !CHECK: %[[OFF_PTR_CALC_1:.*]] = sub i64 %[[OFF_PTR_CALC_0]], 0 !CHECK: %[[OFF_PTR_CALC_2:.*]] = add i64 %[[OFF_PTR_CALC_1]], 1 !CHECK: %[[OFF_PTR_CALC_3:.*]] = mul i64 1, %[[OFF_PTR_CALC_2]] @@ -838,7 +843,7 @@ end subroutine mapType_common_block_members !CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 !CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 !CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 4 -!CHECK: store ptr %[[SZ_CALC_6]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: store ptr %[[SZ_CALC_8]], ptr %[[OFFLOAD_PTR_ARR]], align 8 !CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 !CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 !CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 5 diff --git a/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 b/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 new file mode 100644 index 0000000000000..dd8721b97dccd --- /dev/null +++ b/flang/test/Lower/OpenMP/map-neg-alloca-derived-type-array.f90 @@ -0,0 +1,27 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +subroutine map_negative_bounds_allocatable_dtype() + type derived_type + real(4), pointer :: data(:,:,:) => null() + end type + type(derived_type), allocatable :: dtype(:,:) + + !$omp target map(tofrom: dtype(-1,1)%data) + dtype(-1,1)%data(1,1,1) = 10 + !$omp end target +end subroutine + +! CHECK: %[[VAL_1:.*]] = arith.constant -1 : i64 +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i64) -> index +! CHECK: %[[VAL_3:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i64) -> index +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %{{.*}}, %[[VAL_5]] : (!fir.box>>}>>>>, index) -> (index, index, index) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_8:.*]]:3 = fir.box_dims %{{.*}}, %[[VAL_7]] : (!fir.box>>}>>>>, index) -> (index, index, index) +! CHECK: %[[VAL_9:.*]] = fir.shape_shift %[[VAL_6]]#0, %[[VAL_6]]#1, %[[VAL_8]]#0, %[[VAL_8]]#1 : (index, index, index, index) -> !fir.shapeshift<2> +! CHECK: %[[VAL_10:.*]] = fir.array_coor %{{.*}}(%[[VAL_9]]) %[[VAL_2]], %[[VAL_4]] : (!fir.heap>>}>>>, !fir.shapeshift<2>, index, index) -> !fir.ref>>}>> +! CHECK: %[[VAL_11:.*]] = fir.coordinate_of %[[VAL_10]], data : (!fir.ref>>}>>) -> !fir.ref>>> +! CHECK: %[[VAL_12:.*]] = fir.box_offset %[[VAL_11]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +! CHECK: %[[VAL_13:.*]] = omp.map.info var_ptr(%[[VAL_11]] : !fir.ref>>>, f32) map_clauses(tofrom) capture(ByRef) var_ptr_ptr(%[[VAL_12]] : !fir.llvm_ptr>>) bounds({{.*}}) -> !fir.llvm_ptr>> {name = ""} +! CHECK: %[[VAL_14:.*]] = omp.map.info var_ptr(%[[VAL_11]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {name = {{.*}}}