[flang-commits] [flang] [FIRToMemRef] Fix wrong indexing for converted array_coor over sliced fir.embox (PR #207749)

Kareem Ergawy via flang-commits flang-commits at lists.llvm.org
Tue Jul 7 03:56:31 PDT 2026


================
@@ -814,13 +912,52 @@ FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
   } else {
     Value oneIdx =
         arith::ConstantIndexOp::create(rewriter, arrayCoorOp->getLoc(), 1);
+    // shapeVec is populated by collectSliceInfoFrom in the order:
+    //   [<arrayCoor's shape>, <embox/rebox's shape>]
+    // When both contribute (firMemrefIsEmbox && arrayCoorOp has a slice), the
+    // first `rank` entries are the *box's* shape (= slice extents) while the
+    // next `rank` are the underlying *parent's* extents. Strides for the
+    // reinterpret_cast must come from the parent's contiguous element strides,
+    // not the slice extents (using the latter yields an outer stride that
+    // walks by the slice's size instead of the parent's leading dim).
+    //
+    // Example -- 4x2 parent, slice a(1:2, :) keeping 2 elements per dim:
+    //   %parent : !fir.ref<!fir.array<4x2xi32>>
+    //   %shape  = fir.shape %c4, %c2
+    //   %eslc   = fir.slice %c1, %c2, %c1, %c1, %c2, %c1    ; a(1:2, :)
+    //   %box    = fir.embox %parent(%shape) [%eslc]
+    //                                             :
+    //                                             !fir.box<!fir.array<2x2xi32>>
+    //   ...  %addr = fir.array_coor %box(...) [%innerSlc] %i, %j
+    //
+    // After collectSliceInfoFrom is called on both the array_coor and the
+    // embox, shapeVec becomes (four entries, Fortran order):
+    //   [ box_dim0_extent(=2), box_dim1_extent(=2),         ; array_coor shape
+    //     parent_dim0_extent(=4), parent_dim1_extent(=2) ]  ; embox shape
+    //
+    // For rank = 2 the loop below emits (memref order, outer -> inner):
+    //   size[outer]   = shapeVec[1]                       = 2  (slice's dim1)
+    //   stride[outer] = shapeVec[parentShapeBase + 0]     = 4  (parent's dim0)
+    //   size[inner]   = shapeVec[0]                       = 2  (slice's dim0)
+    //   stride[inner] = 1
+    //
+    // Without the `parentShapeBase` shift, `stride[outer]` would be
+    // `shapeVec[0] = 2` -- the slice's own extent -- and successive outer
+    // steps would walk by 2 elements instead of the parent's 4-element row,
+    // clobbering the wrong columns.
+    const bool hasParentShape = firMemrefIsEmbox && arrayCoorOp.getSlice() &&
+                                shapeVec.size() >= 2 * rank;
----------------
ergawy wrote:

Yet another bug you uncovered. I should have used `boxRank + arrayCoordRank` not `rank * 2`. And, variable naming was a bit confusing so it is hopefully better now. Added a test.

https://github.com/llvm/llvm-project/pull/207749


More information about the flang-commits mailing list