blob: 62235c94680a2952bcc12f62de251380cc8c9881 [file] [edit]
// RUN: fir-opt %s --fir-to-memref | FileCheck %s
// Verify that when both the embox and the array_coor carry a slice, the
// embox's per-dim (lb - 1) shift is folded into the memref indices.
func.func @emboxed_slice_array_coor(%arg0: !fir.ref<!fir.array<4x2xi32>>) -> i32 {
%c1 = arith.constant 1 : index
%c2 = arith.constant 2 : index
%c4 = arith.constant 4 : index
%ci = arith.constant 1 : i64
%shape = fir.shape %c4, %c2 : (index, index) -> !fir.shape<2>
// Embox slice: a(2:2, 1:1) -- Fortran dim-0 lb = 2, dim-1 lb = 1.
%eslice = fir.slice %c2, %c2, %c1, %c1, %c1, %c1
: (index, index, index, index, index, index) -> !fir.slice<2>
%box = fir.embox %arg0(%shape) [%eslice]
: (!fir.ref<!fir.array<4x2xi32>>, !fir.shape<2>, !fir.slice<2>)
-> !fir.box<!fir.array<1x1xi32>>
// Inner array_coor slice (identity 1:1:1 in both dims).
%ashape = fir.shape %c1, %c1 : (index, index) -> !fir.shape<2>
%islice = fir.slice %c1, %c1, %c1, %c1, %c1, %c1
: (index, index, index, index, index, index) -> !fir.slice<2>
%addr = fir.array_coor %box(%ashape) [%islice] %ci, %c1
: (!fir.box<!fir.array<1x1xi32>>, !fir.shape<2>, !fir.slice<2>, i64, index)
-> !fir.ref<i32>
%v = fir.load %addr : !fir.ref<i32>
return %v : i32
}
// CHECK-LABEL: func.func @emboxed_slice_array_coor(
// CHECK-SAME: %[[ARG0:.+]]: !fir.ref<!fir.array<4x2xi32>>) -> i32
// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
// CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index
// CHECK-DAG: %[[C4:.+]] = arith.constant 4 : index
// Parent fir.shape and embox fir.slice survive to the emitted module.
// CHECK: %[[SHAPE:.+]] = fir.shape %[[C4]], %[[C2]] : (index, index) -> !fir.shape<2>
// CHECK: %[[ESLICE:.+]] = fir.slice %[[C2]], %[[C2]], %[[C1]], %[[C1]], %[[C1]], %[[C1]] : ({{.+}}) -> !fir.slice<2>
// CHECK: fir.embox %[[ARG0]](%[[SHAPE]]) [%[[ESLICE]]] : ({{.+}}) -> !fir.box<!fir.array<1x1xi32>>
// Row-major memref view of the parent (col-major !fir.array<4x2>).
// CHECK: %[[MEMREF:.+]] = fir.convert %[[ARG0]] : (!fir.ref<!fir.array<4x2xi32>>) -> memref<2x4xi32>
// Anchor: `arith.constant 0 : index` appears exactly twice between the
// fir.convert and the fold -- once for getMemrefIndices' zero placeholder,
// then again as the reinterpret_cast offset. The fold's `cOne` is emitted
// immediately after the second.
// CHECK: arith.constant 0 : index
// CHECK: arith.constant 0 : index
// CHECK-NEXT: %[[CONE:.+]] = arith.constant 1 : index
// Fortran dim 0 (embox lb = 2, stride = 1) -> delta 1, added onto memref
// position 1.
// CHECK-NEXT: %[[LB0_DELTA:.+]] = arith.subi %[[C2]], %[[CONE]] : index
// CHECK-NEXT: %[[SCALED0:.+]] = arith.muli %{{.+}}, %[[C1]] : index
// CHECK-NEXT: %[[IDX_DIM0:.+]] = arith.addi %[[SCALED0]], %[[LB0_DELTA]] : index
// Fortran dim 1 (embox lb = 1, stride = 1) -> delta 0, added onto memref
// position 0.
// CHECK-NEXT: %[[LB1_DELTA:.+]] = arith.subi %[[C1]], %[[CONE]] : index
// CHECK-NEXT: %[[SCALED1:.+]] = arith.muli %{{.+}}, %[[C1]] : index
// CHECK-NEXT: %[[IDX_DIM1:.+]] = arith.addi %[[SCALED1]], %[[LB1_DELTA]] : index
// reinterpret_cast: offset stays a plain 0 constant, sizes = slice extents
// (1, 1), strides = [parent's dim-0 element stride, 1] in memref order.
// CHECK-NEXT: memref.reinterpret_cast %[[MEMREF]] to offset: [%{{.+}}], sizes: [%[[C1]], %[[C1]]], strides: [%[[C4]], %{{.+}}] : memref<2x4xi32> to memref<?x?xi32, strided<[?, ?], offset: ?>>
// memref.load consumes the shifted indices in memref order
// (dim 1 outer -> IDX_DIM1, dim 0 inner -> IDX_DIM0).
// CHECK-NEXT: memref.load %{{.+}}[%[[IDX_DIM1]], %[[IDX_DIM0]]] : memref<?x?xi32, strided<[?, ?], offset: ?>>