diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp index 3b0b4bc007e6..4f8c8582fb0e 100644 --- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp +++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp @@ -485,15 +485,16 @@ FIRToMemRef::getMemrefIndices(fir::ArrayCoorOp arrayCoorOp, Operation *memref, Value sliceLb = isSliced ? sliceLbs[i] : shift; // When the array_coor has an explicit slice with a shape_shift (i.e. - // non-default lower bounds), the indices are Fortran indices; subtract - // the slice lower bound to get 0-based memref indices. Otherwise (the - // slice comes from an embox, or the shape has no shift), the indices - // are 1-based section indices; subtract 1. + // non-default lower bounds), the indices are in the shape_shift + // coordinate space; subtract the lower bound (shift) to get 0-based + // memref indices. Otherwise (the slice comes from an embox, or the + // shape has no shift), the indices are 1-based section indices; + // subtract 1. bool indicesAreFortran = isShifted && arrayCoorOp.getSlice() != nullptr; Value indexAdjustment = (isSliced && !indicesAreFortran) ? arith::ConstantIndexOp::create(rewriter, loc, 1) - : sliceLb; + : shift; Value delta = arith::SubIOp::create(rewriter, loc, index, indexAdjustment); Value scaled = arith::MulIOp::create(rewriter, loc, delta, stride); diff --git a/flang/test/Transforms/FIRToMemRef/array-coor-slice-shift.mlir b/flang/test/Transforms/FIRToMemRef/array-coor-slice-shift.mlir index f1fb23e0ff9f..22b69a3fa9e6 100644 --- a/flang/test/Transforms/FIRToMemRef/array-coor-slice-shift.mlir +++ b/flang/test/Transforms/FIRToMemRef/array-coor-slice-shift.mlir @@ -1,8 +1,5 @@ // Verify fir.array_coor with explicit shape_shift and slice correctly -// computes 0-based memref indices when lower bounds are non-default. -// This pattern arises after inlining canonicalizes fir.embox+fir.array_coor -// into a single fir.array_coor with explicit shape and slice operands, -// where the indices become Fortran indices rather than 1-based section indices. +// computes 0-based memref indices. // // RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s @@ -47,3 +44,33 @@ func.func @array_coor_slice_shift_2d() { fir.store %c1_i32 to %4 : !fir.ref return } + +// A(1:6, 1:9) with section A(:, 2:4). (default lb=1, slice starts at 2) +// Index (1, 1) = lower bounds => memref indices must be (1, 0). +// The slice offset for dim 2 (sliceLb=2, shift=1 => offset=1) must be +// preserved, not cancelled out. +// CHECK-LABEL: func.func @array_coor_slice_shift_section +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// The dim 2 offset = sliceLb - shift = 2 - 1 = 1: +// CHECK: arith.subi %[[C2]], %[[C1]] : index +// CHECK: memref.store +// CHECK-NOT: fir.array_coor +func.func @array_coor_slice_shift_section() { + %c1 = arith.constant 1 : index + %c2 = arith.constant 2 : index + %c4 = arith.constant 4 : index + %c6 = arith.constant 6 : index + %c9 = arith.constant 9 : index + %c1_i32 = arith.constant 1 : i32 + %0 = fir.alloca !fir.array<6x9xi32> {bindc_name = "a", uniq_name = "_QFEa"} + %1 = fir.shape_shift %c1, %c6, %c1, %c9 : (index, index, index, index) -> !fir.shapeshift<2> + %2 = fir.declare %0(%1) {uniq_name = "_QFEa"} : (!fir.ref>, !fir.shapeshift<2>) -> !fir.ref> + // Slice: full range in dim 1, section 2:4 in dim 2. + %3 = fir.slice %c1, %c6, %c1, %c2, %c4, %c1 : (index, index, index, index, index, index) -> !fir.slice<2> + // Index (1, 1) in shape_shift space. Dim 2 slice starts at 2, + // so memref index for dim 2 must be (1-1)+(2-1) = 1, not 0. + %4 = fir.array_coor %2(%1) [%3] %c1, %c1 : (!fir.ref>, !fir.shapeshift<2>, !fir.slice<2>, index, index) -> !fir.ref + fir.store %c1_i32 to %4 : !fir.ref + return +}