[flang-commits] [flang] [flang] Lowering FIR memory ops to MemRef dialect (PR #173507)
Susan Tan ス-ザン タン via flang-commits
flang-commits at lists.llvm.org
Wed Dec 24 12:53:05 PST 2025
https://github.com/SusanTan updated https://github.com/llvm/llvm-project/pull/173507
>From 3cebdb4f6fd03ef1ea466a51df25d7a899bc6d4b Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 24 Dec 2025 12:02:54 -0800
Subject: [PATCH 1/3] [flang] Lowering FIR memory ops to MemRef dialect
This patch introduces FIRToMemRef, a lowering pass that converts FIR memory operations to the MemRef dialect, including support for slices, shifts, and descriptor-style access patterns. To support partial lowering, where FIR and MemRef types can coexist, we extend the handling of fir.convert to correctly marshal between FIR reference-like types and MemRef descriptors. The patch also factors the type conversion logic into a reusable FIRToMemRefTypeConverter, which centralizes the rules for converting FIR types (e.g. !fir.ref, !fir.box, sequences, logicals) to their corresponding memref types, and is used throughout the new pass.
Co-authored-by: Scott Manley <rscottmanley at gmail.com>
---
.../Transforms/FIRToMemRefTypeConverter.h | 226 ++++
.../flang/Optimizer/Transforms/Passes.td | 12 +
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 60 +-
flang/lib/Optimizer/Transforms/CMakeLists.txt | 1 +
.../lib/Optimizer/Transforms/FIRToMemRef.cpp | 1171 +++++++++++++++++
flang/test/Fir/convert-memref-codegen.mlir | 29 +-
flang/test/Transforms/FIRToMemRef/alloca.mlir | 97 ++
.../Transforms/FIRToMemRef/array-coor-op.mlir | 47 +
.../test/Transforms/FIRToMemRef/complex.mlir | 18 +
.../Transforms/FIRToMemRef/cuda-alloca.mlir | 14 +
.../Transforms/FIRToMemRef/derived-types.mlir | 31 +
flang/test/Transforms/FIRToMemRef/index.mlir | 31 +
.../FIRToMemRef/load-dynamic-shape.mlir | 130 ++
.../FIRToMemRef/load-shift-dynamic.mlir | 169 +++
.../FIRToMemRef/load-shift-static.mlir | 114 ++
.../FIRToMemRef/load-static-shape.mlir | 70 +
.../test/Transforms/FIRToMemRef/logical.mlir | 30 +
.../Transforms/FIRToMemRef/marshal-opt.mlir | 206 +++
.../Transforms/FIRToMemRef/no-declare.mlir | 51 +
.../FIRToMemRef/reject-conversions.mlir | 29 +
.../test/Transforms/FIRToMemRef/replace.mlir | 29 +
flang/test/Transforms/FIRToMemRef/slice.mlir | 372 ++++++
.../FIRToMemRef/store-dynamic-shape.mlir | 129 ++
.../FIRToMemRef/store-shift-static.mlir | 118 ++
.../FIRToMemRef/store-static-shape.mlir | 75 ++
.../test/Transforms/FIRToMemRef/tbaa-tag.mlir | 44 +
26 files changed, 3292 insertions(+), 11 deletions(-)
create mode 100644 flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
create mode 100644 flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
create mode 100644 flang/test/Transforms/FIRToMemRef/alloca.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/array-coor-op.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/complex.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/cuda-alloca.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/derived-types.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/index.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/load-shift-static.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/load-static-shape.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/logical.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/marshal-opt.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/no-declare.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/reject-conversions.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/replace.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/slice.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/store-shift-static.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/store-static-shape.mlir
create mode 100644 flang/test/Transforms/FIRToMemRef/tbaa-tag.mlir
diff --git a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
new file mode 100644
index 0000000000000..d0907ecdd6160
--- /dev/null
+++ b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
@@ -0,0 +1,226 @@
+//===- FIRToMemRefTypeConverter.h - FIR type conversion to MemRef -*- C++
+//-*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines `FIRToMemRefTypeConverter`, a helper used by the
+// FIR-to-MemRef conversion pass to convert FIR types (scalars, arrays,
+// descriptors) into MemRef types suitable for the MemRef dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_FIRTOMEMREFTYPECONVERTER_H
+#define FORTRAN_OPTIMIZER_TRANSFORMS_FIRTOMEMREFTYPECONVERTER_H
+
+#include "flang/Optimizer/Dialect/FIRDialect.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Dialect/Support/FIRContext.h"
+#include "flang/Optimizer/Dialect/Support/KindMapping.h"
+
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace fir {
+
+class FIRToMemRefTypeConverter : public mlir::TypeConverter {
+private:
+ KindMapping kindMapping;
+ bool convertComplexTypes = false;
+ bool convertScalarTypesOnly = false;
+
+public:
+ explicit FIRToMemRefTypeConverter(mlir::ModuleOp mod)
+ : kindMapping(fir::getKindMapping(mod)) {
+ addConversion([](mlir::Type type) { return type; });
+
+ addConversion([&](fir::LogicalType type) -> mlir::Type {
+ return mlir::IntegerType::get(
+ type.getContext(), kindMapping.getLogicalBitsize(type.getFKind()));
+ });
+
+ addSourceMaterialization([](mlir::OpBuilder &builder, mlir::Type type,
+ mlir::ValueRange inputs,
+ mlir::Location loc) -> mlir::Value {
+ assert(!inputs.empty() && "expected a single input for materialization");
+ builder.setInsertionPointAfter(inputs[0].getDefiningOp());
+ return fir::ConvertOp::create(builder, loc, type, inputs[0]);
+ });
+
+ addTargetMaterialization([](mlir::OpBuilder &builder, mlir::Type type,
+ mlir::ValueRange inputs,
+ mlir::Location loc) -> mlir::Value {
+ return fir::ConvertOp::create(builder, loc, type, inputs[0]);
+ });
+ }
+
+ /// Control whether complex types are considered convertible.
+ void setConvertComplexTypes(bool value) { convertComplexTypes = value; }
+
+ /// Control whether only scalar types are considered during convertibleType.
+ void setConvertScalarTypesOnly(bool value) { convertScalarTypesOnly = value; }
+
+ /// Return true if the given FIR type can be converted to a MemRef-typed
+ /// descriptor (i.e. is a supported base element for MemRef marshaling).
+ bool convertibleMemrefType(mlir::Type ty) {
+ if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(ty)) {
+ auto elTy = refTy.getElementType();
+ return convertibleMemrefType(elTy);
+ } else if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(ty)) {
+ auto elTy = pointerTy.getElementType();
+ return convertibleMemrefType(elTy);
+ } else if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty)) {
+ auto elTy = heapTy.getElementType();
+ return convertibleMemrefType(elTy);
+ } else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) {
+ auto elTy = seqTy.getElementType();
+ return convertibleMemrefType(elTy);
+ } else if (auto boxTy = mlir::dyn_cast<fir::BoxType>(ty)) {
+ auto elTy = boxTy.getElementType();
+ return convertibleMemrefType(elTy);
+ }
+
+ setConvertScalarTypesOnly(true);
+ bool result = convertibleType(ty);
+ setConvertScalarTypesOnly(false);
+ return result;
+ }
+
+ /// Return true if the given FIR type represents an empty array (has a zero
+ /// extent in its shape).
+ bool isEmptyArray(mlir::Type ty) const {
+ if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(ty)) {
+ auto elTy = refTy.getElementType();
+ return isEmptyArray(elTy);
+ } else if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(ty)) {
+ auto elTy = pointerTy.getElementType();
+ return isEmptyArray(elTy);
+ } else if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty)) {
+ auto elTy = heapTy.getElementType();
+ return isEmptyArray(elTy);
+ } else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) {
+ llvm::ArrayRef<int64_t> firShape = seqTy.getShape();
+ for (auto shape : firShape) {
+ if (shape == 0)
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ /// Returns true if the given type can be converted according to the current
+ /// converter settings (scalar-only or full).
+ bool convertibleType(mlir::Type type) const {
+ if (!convertScalarTypesOnly) {
+ if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(type)) {
+ auto elTy = refTy.getElementType();
+ if (mlir::isa<fir::SequenceType>(elTy))
+ return false;
+ return convertibleType(elTy);
+ }
+
+ if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(type)) {
+ auto elTy = seqTy.getElementType();
+ return convertibleType(elTy);
+ }
+ }
+
+ if (fir::isa_fir_type(type)) {
+ if (mlir::isa<fir::LogicalType>(type))
+ return true;
+ return false;
+ }
+
+ if (type.isUnsignedInteger())
+ return false;
+
+ if (mlir::isa<mlir::ComplexType>(type))
+ return convertComplexTypes;
+
+ if (mlir::isa<mlir::FunctionType>(type))
+ return false;
+
+ if (mlir::isa<mlir::TupleType>(type))
+ return false;
+
+ return true;
+ }
+
+ /// Convert a FIR element / aggregate type to a MemRef descriptor type.
+ mlir::MemRefType convertMemrefType(mlir::Type firTy) const {
+ auto convertBaseType = [&](mlir::Type firTy) -> mlir::MemRefType {
+ if (auto charTy = mlir::dyn_cast<fir::CharacterType>(firTy)) {
+ unsigned kind = charTy.getFKind();
+ unsigned bitWidth = kindMapping.getCharacterBitsize(kind);
+ mlir::Type elTy = mlir::IntegerType::get(charTy.getContext(), bitWidth);
+
+ if (charTy.hasConstantLen() && charTy.getLen() == 1) {
+ return mlir::MemRefType::get({}, elTy);
+ } else if (charTy.hasConstantLen()) {
+ int64_t len = charTy.getLen();
+ return mlir::MemRefType::get({len}, elTy);
+ } else {
+ return mlir::MemRefType::get({mlir::ShapedType::kDynamic}, elTy);
+ }
+ }
+
+ if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(firTy)) {
+ auto elTy = seqTy.getElementType();
+ mlir::Type ty = convertType(elTy);
+
+ llvm::ArrayRef<int64_t> firShape = seqTy.getShape();
+ llvm::SmallVector<int64_t> shape;
+ for (auto it = firShape.rbegin(); it != firShape.rend(); ++it)
+ shape.push_back(*it);
+
+ assert(mlir::BaseMemRefType::isValidElementType(ty) &&
+ "got invalid memref element type from array fir type");
+ return mlir::MemRefType::get(shape, ty);
+ }
+
+ mlir::Type ty = convertType(firTy);
+ assert(mlir::BaseMemRefType::isValidElementType(ty) &&
+ "got invalid memref element type from scalar fir type");
+ return mlir::MemRefType::get({}, ty);
+ };
+
+ if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(firTy)) {
+ auto elTy = refTy.getElementType();
+ return convertBaseType(elTy);
+ }
+
+ if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(firTy)) {
+ auto elTy = pointerTy.getElementType();
+ return convertBaseType(elTy);
+ }
+
+ if (auto heapTy = mlir::dyn_cast<fir::HeapType>(firTy)) {
+ auto elTy = heapTy.getElementType();
+ return convertBaseType(elTy);
+ }
+
+ if (auto boxTy = mlir::dyn_cast<fir::BoxType>(firTy)) {
+ auto elTy = boxTy.getElementType();
+
+ auto memRefTy = convertMemrefType(elTy);
+ mlir::MemRefType dynTy = mlir::MemRefType::Builder(memRefTy).setLayout(
+ mlir::StridedLayoutAttr::get(
+ memRefTy.getContext(), mlir::ShapedType::kDynamic,
+ llvm::SmallVector<int64_t>(memRefTy.getRank(),
+ mlir::ShapedType::kDynamic)));
+ return dynTy;
+ }
+
+ return convertBaseType(firTy);
+ }
+};
+
+} // namespace fir
+
+#endif // FORTRAN_OPTIMIZER_TRANSFORMS_FIRTOMEMREFTYPECONVERTER_H
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index f50202784e2dc..f52dae511ada1 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -215,6 +215,18 @@ def MemRefDataFlowOpt : Pass<"fir-memref-dataflow-opt", "::mlir::func::FuncOp">
];
}
+def FIRToMemRef : Pass<"fir-to-memref", "::mlir::func::FuncOp"> {
+ let summary = "Convert FIR loads, stores, and descriptors to MemRef dialect";
+ let description = [{
+ Lower FIR memory operations (`fir.alloca`, `fir.load`, `fir.store`, 'fir.array_coor') to MLIR's MemRef core dialect.
+ }];
+ let dependentDialects = ["fir::FIROpsDialect", "mlir::arith::ArithDialect",
+ "mlir::func::FuncDialect",
+ "mlir::memref::MemRefDialect",
+ "mlir::scf::SCFDialect", "mlir::omp::OpenMPDialect",
+ "mlir::acc::OpenACCDialect"];
+}
+
// This needs to be a "mlir::ModuleOp" pass, because we are creating debug for
// the module in this pass.
def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> {
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 55e885d46d351..c5aadb4beac55 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -39,6 +39,7 @@
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h"
+#include "mlir/Conversion/LLVMCommon/MemRefBuilder.h"
#include "mlir/Conversion/LLVMCommon/Pattern.h"
#include "mlir/Conversion/MathToFuncs/MathToFuncs.h"
#include "mlir/Conversion/MathToLLVM/MathToLLVM.h"
@@ -817,13 +818,58 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
auto fromFirTy = convert.getValue().getType();
auto toFirTy = convert.getRes().getType();
- // Let more specialized conversions (e.g. FIR to memref
- // converters) handle fir.convert when either side is a memref. This
- // avoids interfering with descriptor-based flows such as fir.box /
- // fir.box_addr and keeps this pattern focused on value conversions.
- if (mlir::isa<mlir::MemRefType>(fromFirTy) ||
- mlir::isa<mlir::MemRefType>(toFirTy))
- return mlir::failure();
+ // Handle conversions between pointer-like values and memref descriptors.
+ // These are produced by FIR-to-MemRef lowering and represent descriptor
+ // marshaling rather than pure value conversions.
+ if (auto memRefTy = mlir::dyn_cast<mlir::MemRefType>(toFirTy)) {
+ mlir::Location loc = convert.getLoc();
+ mlir::Value basePtr = adaptor.getValue();
+ assert(basePtr && "null base pointer");
+
+ auto [strides, offset] = memRefTy.getStridesAndOffset();
+ bool hasStaticLayout =
+ mlir::ShapedType::isStatic(offset) &&
+ llvm::none_of(strides, mlir::ShapedType::isDynamic);
+
+ auto *firConv =
+ static_cast<const fir::LLVMTypeConverter *>(this->getTypeConverter());
+ assert(firConv && "expected non-null LLVMTypeConverter");
+
+ if (memRefTy.hasStaticShape() && hasStaticLayout) {
+ // Static shape and layout: build a fully-populated descriptor.
+ mlir::Value memrefDesc = mlir::MemRefDescriptor::fromStaticShape(
+ rewriter, loc, *firConv, memRefTy, basePtr);
+ rewriter.replaceOp(convert, memrefDesc);
+ return mlir::success();
+ }
+
+ // Dynamic shape or layout: create an LLVM memref descriptor and insert
+ // the base pointer field, letting the rest of the fields be populated
+ // by subsequent lowering.
+ mlir::Type llvmMemRefTy = firConv->convertType(memRefTy);
+ auto undef = mlir::LLVM::UndefOp::create(rewriter, loc, llvmMemRefTy);
+ auto insert =
+ mlir::LLVM::InsertValueOp::create(rewriter, loc, undef, basePtr, 1);
+ rewriter.replaceOp(convert, insert);
+ return mlir::success();
+ }
+
+ if (auto memRefTy = mlir::dyn_cast<mlir::MemRefType>(fromFirTy)) {
+ // Legalize conversions *from* memref descriptors to pointer-like values
+ // by extracting the underlying buffer pointer from the descriptor.
+ mlir::Location loc = convert.getLoc();
+ mlir::Value base = adaptor.getValue();
+ auto alignedPtr =
+ mlir::LLVM::ExtractValueOp::create(rewriter, loc, base, 1);
+ auto offset = mlir::LLVM::ExtractValueOp::create(rewriter, loc, base, 2);
+ mlir::Type elementType =
+ this->getTypeConverter()->convertType(memRefTy.getElementType());
+ auto gepOp = mlir::LLVM::GEPOp::create(rewriter, loc,
+ alignedPtr.getType(), elementType,
+ alignedPtr, offset.getResult());
+ rewriter.replaceOp(convert, gepOp);
+ return mlir::success();
+ }
auto fromTy = convertType(fromFirTy);
auto toTy = convertType(toFirTy);
diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt
index 619f3adc67c85..b8bab68328555 100644
--- a/flang/lib/Optimizer/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt
@@ -18,6 +18,7 @@ add_flang_library(FIRTransforms
ArrayValueCopy.cpp
ExternalNameConversion.cpp
FIRToSCF.cpp
+ FIRToMemRef.cpp
MemoryUtils.cpp
MemoryAllocation.cpp
StackArrays.cpp
diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
new file mode 100644
index 0000000000000..c79425c8a21d2
--- /dev/null
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -0,0 +1,1171 @@
+//===-- FIRToMemRef.cpp - Convert FIR loads and stores to MemRef ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass lowers FIR dialect memory operations to the MemRef dialect.
+// It is adapted from the NVHPC FIRToMemRef implementation so that it can
+// be used as a regular flang/MLIR transform pass.
+//
+// In particular it:
+//
+// - Rewrites `fir.alloca` to `memref.alloca`.
+//
+// - Rewrites `fir.load` / `fir.store` to `memref.load` / `memref.store`.
+//
+// - Marshals FIR reference-like values (boxes, array coordinates,
+// embox/rebox, and optionals) into MemRef descriptors by introducing
+// `fir.convert` at use sites. For example:
+//
+// %fir_ref = ... : !fir.ref<!fir.array<...>>
+// %memref = fir.convert %fir_ref : !fir.ref<!fir.array<...>> ->
+// memref<...> %val = memref.load %memref[...] : memref<...> fir.call
+// @callee(%fir_ref) : (!fir.ref<!fir.array<...>>) -> ()
+//
+// Here the MemRef-typed value is used for `memref.load`, while the original
+// FIR-typed value is preserved for `fir.call`.
+//
+// - Computes shapes, strides, and indices as needed for slices and shifts
+// and emits `memref.reinterpret_cast` when dynamic layout is required.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h"
+#include "flang/Optimizer/Transforms/Passes.h"
+
+#include "flang/Optimizer/Builder/CUFCommon.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/Dialect/Support/FIRContext.h"
+#include "flang/Optimizer/Dialect/Support/KindMapping.h"
+
+#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
+#include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/IR/Block.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dominance.h"
+#include "mlir/IR/Location.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/IR/Region.h"
+#include "mlir/IR/Value.h"
+#include "mlir/IR/ValueRange.h"
+#include "mlir/IR/Verifier.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Support/LLVM.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#define DEBUG_TYPE "fir-to-memref"
+
+using namespace mlir;
+
+namespace fir {
+
+#define GEN_PASS_DEF_FIRTOMEMREF
+#include "flang/Optimizer/Transforms/Passes.h.inc"
+
+static bool isMarshalLike(Operation *op) {
+ if (!op)
+ return false;
+
+ auto convert = dyn_cast<fir::ConvertOp>(op);
+ if (!convert)
+ return false;
+
+ bool resIsMemRef = isa<MemRefType>(convert.getType());
+ bool argIsMemRef = isa<MemRefType>(convert.getValue().getType());
+
+ assert(!(resIsMemRef && argIsMemRef) &&
+ "unexpected fir.convert memref -> memref in isMarshalLike");
+
+ return resIsMemRef || argIsMemRef;
+}
+
+using MemRefInfo = FailureOr<std::pair<Value, SmallVector<Value>>>;
+
+static llvm::cl::opt<bool> enableFIRConvertOptimizations(
+ "enable-fir-convert-opts",
+ llvm::cl::desc("enable emilinating redundant fir.convert in FIR-to-MemRef"),
+ llvm::cl::init(false), llvm::cl::Hidden);
+
+class FIRToMemRef : public fir::impl::FIRToMemRefBase<FIRToMemRef> {
+public:
+ void runOnOperation() override;
+
+private:
+ llvm::SmallSetVector<Operation *, 32> eraseOps;
+
+ DominanceInfo *domInfo = nullptr;
+
+ void rewriteAlloca(fir::AllocaOp, PatternRewriter &,
+ FIRToMemRefTypeConverter &);
+
+ void rewriteLoadOp(fir::LoadOp, PatternRewriter &,
+ FIRToMemRefTypeConverter &);
+
+ void rewriteStoreOp(fir::StoreOp, PatternRewriter &,
+ FIRToMemRefTypeConverter &);
+
+ MemRefInfo getMemRefInfo(Value, PatternRewriter &, FIRToMemRefTypeConverter &,
+ Operation *);
+
+ MemRefInfo marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp,
+ PatternRewriter &, FIRToMemRefTypeConverter &);
+
+ void replaceFIRMemrefs(Value, Value, PatternRewriter &) const;
+
+ FailureOr<Value> getFIRMarshal(Operation *memOp, Operation *memref,
+ PatternRewriter &, FIRToMemRefTypeConverter &);
+
+ FailureOr<SmallVector<Value>> getMemrefIndices(fir::ArrayCoorOp, Operation *,
+ PatternRewriter &, Value,
+ Value) const;
+
+ bool memrefIsOptional(Operation *) const;
+
+ Value canonicalizeIndex(Value, PatternRewriter &) const;
+
+ template <typename OpTy>
+ void getShapeFrom(OpTy op, SmallVector<Value> &shapeVec,
+ SmallVector<Value> &shiftVec,
+ SmallVector<Value> &sliceVec) const;
+
+ void populateShapeAndShift(SmallVectorImpl<Value> &shapeVec,
+ SmallVectorImpl<Value> &shiftVec,
+ fir::ShapeShiftOp shift) const;
+
+ void populateShift(SmallVectorImpl<Value> &vec, fir::ShiftOp shift) const;
+
+ void populateShape(SmallVectorImpl<Value> &vec, fir::ShapeOp shape) const;
+
+ unsigned getRankFromEmbox(fir::EmboxOp embox) const {
+ auto memrefType = embox.getMemref().getType();
+ Type unwrappedType = fir::unwrapRefType(memrefType);
+ if (auto seqType = dyn_cast<fir::SequenceType>(unwrappedType))
+ return seqType.getDimension();
+ return 0;
+ }
+
+ bool isCompilerGeneratedAlloca(Operation *op) const;
+
+ void copyAttribute(Operation *from, Operation *to,
+ llvm::StringRef name) const;
+
+ Type getBaseType(Type type, bool complexBaseTypes = false) const;
+
+ bool memrefIsDeviceData(Operation *memref) const;
+
+ bool isMarshalLikeOp(Operation *op) const;
+
+ mlir::Attribute findCudaDataAttr(Value val) const;
+};
+
+void FIRToMemRef::populateShapeAndShift(SmallVectorImpl<Value> &shapeVec,
+ SmallVectorImpl<Value> &shiftVec,
+ fir::ShapeShiftOp shift) const {
+ for (auto i = shift.getPairs().begin(), endIter = shift.getPairs().end();
+ i != endIter;) {
+ shiftVec.push_back(*i++);
+ shapeVec.push_back(*i++);
+ }
+}
+
+bool FIRToMemRef::isCompilerGeneratedAlloca(Operation *op) const {
+ if (!isa<fir::AllocaOp, memref::AllocaOp>(op))
+ llvm_unreachable("expected alloca op");
+
+ return !op->getAttr("bindc_name") && !op->getAttr("uniq_name");
+}
+
+void FIRToMemRef::copyAttribute(Operation *from, Operation *to,
+ llvm::StringRef name) const {
+ if (auto value = from->getAttr(name))
+ to->setAttr(name, value);
+}
+
+Type FIRToMemRef::getBaseType(Type type, bool complexBaseTypes) const {
+ if (fir::isa_fir_type(type)) {
+ type = fir::unwrapAllRefAndSeqType(type);
+ type = fir::unwrapSeqOrBoxedSeqType(type);
+ } else if (auto memrefTy = dyn_cast<MemRefType>(type)) {
+ type = memrefTy.getElementType();
+ }
+
+ if (!complexBaseTypes) {
+ if (auto complexTy = dyn_cast<ComplexType>(type))
+ type = complexTy.getElementType();
+ }
+ return type;
+}
+
+bool FIRToMemRef::memrefIsDeviceData(Operation *memref) const {
+ if (isa<ACC_DATA_ENTRY_OPS>(memref))
+ return true;
+
+ if (auto cudaAttr = cuf::getDataAttr(memref)) {
+ auto attrValue = cudaAttr.getValue();
+ return attrValue == cuf::DataAttribute::Device ||
+ attrValue == cuf::DataAttribute::Managed ||
+ attrValue == cuf::DataAttribute::Constant ||
+ attrValue == cuf::DataAttribute::Shared ||
+ attrValue == cuf::DataAttribute::Unified;
+ }
+ return false;
+}
+
+bool FIRToMemRef::isMarshalLikeOp(Operation *op) const {
+ if (!op)
+ return false;
+
+ auto convert = dyn_cast<fir::ConvertOp>(op);
+ if (convert) {
+ bool resIsMemRef = isa<MemRefType>(convert.getType());
+ bool argIsMemRef = isa<MemRefType>(convert.getValue().getType());
+ assert(!(resIsMemRef && argIsMemRef) &&
+ "unexpected fir.convert memref -> memref in isMarshalLikeOp");
+ }
+
+ auto isaPolymorphicConversion = [](fir::ConvertOp c) {
+ bool retVal{false};
+ if (auto fromBoxTy{dyn_cast<fir::ClassType>(
+ fir::unwrapRefType(c.getValue().getType()))}) {
+ if (auto toBoxTy{
+ dyn_cast<fir::BaseBoxType>(fir::unwrapRefType(c.getType()))}) {
+ auto fromEleTy{fir::unwrapAllRefAndSeqType(fromBoxTy.getEleTy())};
+ auto toEleTy{fir::unwrapAllRefAndSeqType(toBoxTy.getEleTy())};
+ if (fromEleTy != toEleTy)
+ retVal = true;
+ }
+ }
+ return retVal;
+ };
+
+ return convert && !isaPolymorphicConversion(convert) &&
+ (isa<MemRefType>(convert.getType()) ||
+ isa<MemRefType>(convert.getValue().getType()));
+}
+
+mlir::Attribute FIRToMemRef::findCudaDataAttr(Value val) const {
+ Value currentVal = val;
+ llvm::SmallPtrSet<Operation *, 8> visited;
+
+ while (currentVal) {
+ auto defOp = currentVal.getDefiningOp();
+ if (!defOp || !visited.insert(defOp).second)
+ break;
+
+ if (auto cudaAttr = cuf::getDataAttr(defOp))
+ return cudaAttr;
+
+ if (auto reboxOp = dyn_cast<fir::ReboxOp>(defOp)) {
+ currentVal = reboxOp.getBox();
+ } else if (auto emboxOp = dyn_cast<fir::EmboxOp>(defOp)) {
+ currentVal = emboxOp.getMemref();
+ } else if (auto declareOp = dyn_cast<fir::DeclareOp>(defOp)) {
+ currentVal = declareOp.getMemref();
+ } else {
+ break;
+ }
+ }
+ return nullptr;
+}
+
+void FIRToMemRef::populateShift(SmallVectorImpl<Value> &vec,
+ fir::ShiftOp shift) const {
+ vec.append(shift.getOrigins().begin(), shift.getOrigins().end());
+}
+
+void FIRToMemRef::populateShape(SmallVectorImpl<Value> &vec,
+ fir::ShapeOp shape) const {
+ vec.append(shape.getExtents().begin(), shape.getExtents().end());
+}
+
+template <typename OpTy>
+void FIRToMemRef::getShapeFrom(OpTy op, SmallVector<Value> &shapeVec,
+ SmallVector<Value> &shiftVec,
+ SmallVector<Value> &sliceVec) const {
+ if constexpr (std::is_same_v<OpTy, fir::ArrayCoorOp> ||
+ std::is_same_v<OpTy, fir::ReboxOp> ||
+ std::is_same_v<OpTy, fir::EmboxOp>) {
+ Value shapeVal = op.getShape();
+
+ if (shapeVal) {
+ Operation *shapeValOp = shapeVal.getDefiningOp();
+
+ if (auto shapeOp = dyn_cast<fir::ShapeOp>(shapeValOp)) {
+ populateShape(shapeVec, shapeOp);
+ } else if (auto shapeShiftOp = dyn_cast<fir::ShapeShiftOp>(shapeValOp)) {
+ populateShapeAndShift(shapeVec, shiftVec, shapeShiftOp);
+ } else if (auto shiftOp = dyn_cast<fir::ShiftOp>(shapeValOp)) {
+ populateShift(shiftVec, shiftOp);
+ }
+ }
+
+ Value sliceVal = op.getSlice();
+ if (sliceVal) {
+ if (auto sliceOp = sliceVal.getDefiningOp<fir::SliceOp>()) {
+ auto triples = sliceOp.getTriples();
+ sliceVec.append(triples.begin(), triples.end());
+ }
+ }
+ }
+}
+
+void FIRToMemRef::rewriteAlloca(fir::AllocaOp firAlloca,
+ PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter) {
+ if (!typeConverter.convertibleType(firAlloca.getInType()))
+ return;
+
+ if (typeConverter.isEmptyArray(firAlloca.getType()))
+ return;
+
+ rewriter.setInsertionPointAfter(firAlloca);
+
+ Type type = firAlloca.getType();
+ MemRefType memrefTy = typeConverter.convertMemrefType(type);
+
+ Location loc = firAlloca.getLoc();
+
+ SmallVector<Value> sizes = firAlloca.getOperands();
+ std::reverse(sizes.begin(), sizes.end());
+
+ auto alloca = memref::AllocaOp::create(rewriter, loc, memrefTy, sizes);
+ copyAttribute(firAlloca, alloca, firAlloca.getBindcNameAttrName());
+ copyAttribute(firAlloca, alloca, firAlloca.getUniqNameAttrName());
+ copyAttribute(firAlloca, alloca, cuf::getDataAttrName());
+
+ auto convert = fir::ConvertOp::create(rewriter, loc, type, alloca);
+
+ rewriter.replaceOp(firAlloca, convert);
+
+ if (isCompilerGeneratedAlloca(alloca)) {
+ for (Operation *userOp : convert->getUsers()) {
+ if (auto declareOp = dyn_cast<fir::DeclareOp>(userOp)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: removing declare for compiler temp:\n";
+ declareOp->dump());
+ declareOp->replaceAllUsesWith(convert);
+ eraseOps.insert(userOp);
+ }
+ }
+ }
+}
+
+bool FIRToMemRef::memrefIsOptional(Operation *op) const {
+ if (auto declare = dyn_cast<fir::DeclareOp>(op)) {
+ Value operand = declare.getMemref();
+
+ if (auto blockArg = dyn_cast<BlockArgument>(operand)) {
+ if (auto func =
+ dyn_cast<func::FuncOp>((blockArg.getOwner())->getParentOp())) {
+ if (func.getArgAttr(blockArg.getArgNumber(),
+ fir::getOptionalAttrName()))
+ return true;
+ }
+ }
+
+ Operation *operandOp = operand.getDefiningOp();
+ if (operandOp && isa<fir::AbsentOp>(operandOp))
+ return true;
+ }
+
+ for (mlir::Value result : op->getResults()) {
+ for (mlir::Operation *userOp : result.getUsers()) {
+ if (isa<fir::IsPresentOp>(userOp))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static Value castTypeToIndexType(Value originalValue,
+ PatternRewriter &rewriter) {
+ if (originalValue.getType().isIndex())
+ return originalValue;
+
+ Type indexType = rewriter.getIndexType();
+ return arith::IndexCastOp::create(rewriter, originalValue.getLoc(), indexType,
+ originalValue);
+}
+
+FailureOr<SmallVector<Value>>
+FIRToMemRef::getMemrefIndices(fir::ArrayCoorOp arrayCoorOp, Operation *memref,
+ PatternRewriter &rewriter, Value marshal,
+ Value one) const {
+ IndexType indexTy = rewriter.getIndexType();
+ SmallVector<Value> indices;
+ Location loc = arrayCoorOp->getLoc();
+ SmallVector<Value> shiftVec, shapeVec, sliceVec;
+ int rank = arrayCoorOp.getIndices().size();
+ getShapeFrom<fir::ArrayCoorOp>(arrayCoorOp, shapeVec, shiftVec, sliceVec);
+
+ if (auto embox = dyn_cast_or_null<fir::EmboxOp>(memref)) {
+ getShapeFrom<fir::EmboxOp>(embox, shapeVec, shiftVec, sliceVec);
+ rank = getRankFromEmbox(embox);
+ }
+
+ SmallVector<Value> sliceLbs, sliceStrides;
+ for (size_t i = 0; i < sliceVec.size(); i += 3) {
+ sliceLbs.push_back(castTypeToIndexType(sliceVec[i], rewriter));
+ sliceStrides.push_back(castTypeToIndexType(sliceVec[i + 2], rewriter));
+ }
+
+ const bool isShifted = !shiftVec.empty();
+ const bool isSliced = !sliceVec.empty();
+
+ ValueRange idxs = arrayCoorOp.getIndices();
+ Value zero = arith::ConstantIndexOp::create(rewriter, loc, 0);
+
+ SmallVector<bool> filledPositions(rank, false);
+ for (int i = 0; i < rank; ++i) {
+ Value step = isSliced ? sliceStrides[i] : one;
+ Operation *stepOp = step.getDefiningOp();
+ if (stepOp && mlir::isa_and_nonnull<fir::UndefOp>(stepOp)) {
+ Value shift = isShifted ? shiftVec[i] : one;
+ Value sliceLb = isSliced ? sliceLbs[i] : shift;
+ Value offset = arith::SubIOp::create(rewriter, loc, sliceLb, shift);
+ indices.push_back(offset);
+ filledPositions[i] = true;
+ } else {
+ indices.push_back(zero);
+ }
+ }
+
+ int arrayCoorIdx = 0;
+ for (int i = 0; i < rank; ++i) {
+ if (filledPositions[i])
+ continue;
+
+ assert((unsigned int)arrayCoorIdx < idxs.size() &&
+ "empty dimension should be eliminated\n");
+ Value index = canonicalizeIndex(idxs[arrayCoorIdx], rewriter);
+ Type cTy = index.getType();
+ if (!llvm::isa<IndexType>(cTy)) {
+ assert(cTy.isSignlessInteger() && "expected signless integer type");
+ index = arith::IndexCastOp::create(rewriter, loc, indexTy, index);
+ }
+
+ Value shift = isShifted ? shiftVec[i] : one;
+ Value stride = isSliced ? sliceStrides[i] : one;
+ Value sliceLb = isSliced ? sliceLbs[i] : shift;
+
+ Value oneIdx = arith::ConstantIndexOp::create(rewriter, loc, 1);
+ Value indexAdjustment = isSliced ? oneIdx : sliceLb;
+ Value delta = arith::SubIOp::create(rewriter, loc, index, indexAdjustment);
+
+ Value scaled = arith::MulIOp::create(rewriter, loc, delta, stride);
+
+ Value offset = arith::SubIOp::create(rewriter, loc, sliceLb, shift);
+
+ Value finalIndex = arith::AddIOp::create(rewriter, loc, scaled, offset);
+
+ indices[i] = finalIndex;
+ arrayCoorIdx++;
+ }
+
+ std::reverse(indices.begin(), indices.end());
+
+ return indices;
+}
+
+MemRefInfo
+FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
+ PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter) {
+ IndexType indexTy = rewriter.getIndexType();
+ Value firMemref = arrayCoorOp.getMemref();
+ if (!typeConverter.convertibleMemrefType(firMemref.getType()))
+ return failure();
+
+ if (typeConverter.isEmptyArray(firMemref.getType()))
+ return failure();
+
+ if (auto blockArg = dyn_cast<BlockArgument>(firMemref)) {
+ Value elemRef = arrayCoorOp.getResult();
+ rewriter.setInsertionPointAfter(arrayCoorOp);
+ Location loc = arrayCoorOp->getLoc();
+ Type elemMemrefTy = typeConverter.convertMemrefType(elemRef.getType());
+ Value marshal =
+ fir::ConvertOp::create(rewriter, loc, elemMemrefTy, elemRef);
+ SmallVector<Value> indices;
+ return std::pair{marshal, indices};
+ }
+
+ Operation *memref = firMemref.getDefiningOp();
+
+ FailureOr<Value> marshal;
+ if (enableFIRConvertOptimizations && isMarshalLike(memref) &&
+ !fir::isa_fir_type(firMemref.getType())) {
+ marshal = firMemref;
+ rewriter.setInsertionPoint(arrayCoorOp);
+ } else {
+ Operation *arrayCoorOperation = arrayCoorOp.getOperation();
+ if (memrefIsOptional(memref)) {
+ rewriter.setInsertionPoint(arrayCoorOp);
+ auto ifOp = arrayCoorOperation->getParentOfType<scf::IfOp>();
+ if (ifOp) {
+ Operation *condition = ifOp.getCondition().getDefiningOp();
+ if (condition && isa<fir::IsPresentOp>(condition)) {
+ if (condition->getOperand(0) == firMemref) {
+ if (arrayCoorOperation->getParentRegion() ==
+ &ifOp.getThenRegion()) {
+ rewriter.setInsertionPointToStart(
+ &(ifOp.getThenRegion().front()));
+ } else if (arrayCoorOperation->getParentRegion() ==
+ &ifOp.getElseRegion()) {
+ rewriter.setInsertionPointToStart(
+ &(ifOp.getElseRegion().front()));
+ }
+ }
+ }
+ }
+ }
+
+ rewriter.setInsertionPoint(arrayCoorOp);
+ marshal = getFIRMarshal(memOp, memref, rewriter, typeConverter);
+ if (failed(marshal))
+ return failure();
+
+ rewriter.setInsertionPointAfter(arrayCoorOp);
+ }
+
+ Location loc = arrayCoorOp->getLoc();
+ Value one = arith::ConstantIndexOp::create(rewriter, loc, 1);
+ FailureOr<SmallVector<Value>> failureOrIndices =
+ getMemrefIndices(arrayCoorOp, memref, rewriter, *marshal, one);
+ if (failed(failureOrIndices))
+ return failure();
+ SmallVector<Value> indices = *failureOrIndices;
+
+ if (marshal == firMemref)
+ return std::pair{*marshal, indices};
+
+ Value marshalVal = *marshal;
+ MemRefType memRefTy = dyn_cast<MemRefType>(marshalVal.getType());
+
+ bool isRebox = firMemref.getDefiningOp<fir::ReboxOp>() != nullptr;
+
+ if (memRefTy.hasStaticShape() && !isRebox)
+ return std::pair{*marshal, indices};
+
+ unsigned rank = arrayCoorOp.getIndices().size();
+
+ if (auto embox = firMemref.getDefiningOp<fir::EmboxOp>()) {
+ rank = getRankFromEmbox(embox);
+ }
+
+ SmallVector<Value> sizes;
+ sizes.reserve(rank);
+ SmallVector<Value> strides;
+ strides.reserve(rank);
+
+ SmallVector<Value> shapeVec, shiftVec, sliceVec;
+ getShapeFrom<fir::ArrayCoorOp>(arrayCoorOp, shapeVec, shiftVec, sliceVec);
+
+ Value box = firMemref;
+ if (!isa<BlockArgument>(firMemref)) {
+ if (auto embox = firMemref.getDefiningOp<fir::EmboxOp>()) {
+ getShapeFrom<fir::EmboxOp>(embox, shapeVec, shiftVec, sliceVec);
+ } else if (auto rebox = firMemref.getDefiningOp<fir::ReboxOp>()) {
+ getShapeFrom<fir::ReboxOp>(rebox, shapeVec, shiftVec, sliceVec);
+ }
+ }
+
+ if (shapeVec.empty()) {
+ auto boxElementSize =
+ fir::BoxEleSizeOp::create(rewriter, loc, indexTy, box);
+
+ for (unsigned i = 0; i < rank; ++i) {
+ Value dim = arith::ConstantIndexOp::create(rewriter, loc, rank - i - 1);
+ auto boxDims = fir::BoxDimsOp::create(rewriter, loc, indexTy, indexTy,
+ indexTy, box, dim);
+
+ Value extent = boxDims->getResult(1);
+ sizes.push_back(castTypeToIndexType(extent, rewriter));
+
+ Value byteStride = boxDims->getResult(2);
+ Value div =
+ arith::DivSIOp::create(rewriter, loc, byteStride, boxElementSize);
+ strides.push_back(castTypeToIndexType(div, rewriter));
+ }
+
+ } else {
+ Value oneIdx =
+ arith::ConstantIndexOp::create(rewriter, arrayCoorOp->getLoc(), 1);
+ for (unsigned i = rank - 1; i > 0; --i) {
+ Value size = shapeVec[i];
+ sizes.push_back(castTypeToIndexType(size, rewriter));
+
+ Value stride = shapeVec[0];
+ for (unsigned j = 1; j <= i - 1; ++j) {
+ stride = arith::MulIOp::create(rewriter, loc, shapeVec[j], stride);
+ }
+ strides.push_back(castTypeToIndexType(stride, rewriter));
+ }
+
+ sizes.push_back(castTypeToIndexType(shapeVec[0], rewriter));
+ strides.push_back(oneIdx);
+ }
+
+ assert(strides.size() == sizes.size() && sizes.size() == rank);
+
+ int64_t dynamicOffset = ShapedType::kDynamic;
+ SmallVector<int64_t> dynamicStrides(rank, ShapedType::kDynamic);
+ auto stridedLayout = StridedLayoutAttr::get(marshalVal.getContext(),
+ dynamicOffset, dynamicStrides);
+
+ SmallVector<int64_t> dynamicShape(rank, ShapedType::kDynamic);
+ memRefTy =
+ MemRefType::get(dynamicShape, memRefTy.getElementType(), stridedLayout);
+
+ Value offset = arith::ConstantIndexOp::create(rewriter, loc, 0);
+
+ auto reinterpret = memref::ReinterpretCastOp::create(
+ rewriter, loc, memRefTy, *marshal, offset, sizes, strides);
+
+ Value result = reinterpret->getResult(0);
+ return std::pair{result, indices};
+}
+
+FailureOr<Value>
+FIRToMemRef::getFIRMarshal(Operation *memOp, Operation *op,
+ PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter) {
+ if (enableFIRConvertOptimizations && !op->hasOneUse() &&
+ !memrefIsOptional(op)) {
+ for (Operation *userOp : op->getUsers()) {
+ if (auto convertOp = dyn_cast<fir::ConvertOp>(userOp)) {
+ Value converted = convertOp.getResult();
+ if (!isa<MemRefType>(converted.getType()))
+ continue;
+
+ if (userOp->getParentOp() == memOp->getParentOp() &&
+ domInfo->dominates(userOp, memOp)) {
+ return converted;
+ }
+ }
+ }
+ }
+
+ assert(op->getNumResults() == 1 && "expecting one result");
+
+ Value basePtr = op->getResult(0);
+
+ MemRefType memrefTy = typeConverter.convertMemrefType(basePtr.getType());
+ Type baseTy = memrefTy.getElementType();
+
+ if (fir::isa_std_type(baseTy) && memrefTy.getRank() == 0) {
+ if (auto convertOp = basePtr.getDefiningOp<fir::ConvertOp>()) {
+ Value input = convertOp.getOperand();
+ if (auto alloca = input.getDefiningOp<memref::AllocaOp>()) {
+ assert(alloca.getType() == memrefTy && "expected same types");
+ if (isCompilerGeneratedAlloca(alloca)) {
+ return alloca.getResult();
+ }
+ }
+ }
+ }
+
+ const Location loc = op->getLoc();
+
+ if (isa<fir::BoxType>(basePtr.getType())) {
+ Operation *baseOp = basePtr.getDefiningOp();
+ auto boxAddrOp = fir::BoxAddrOp::create(rewriter, loc, basePtr);
+
+ if (auto cudaAttr = findCudaDataAttr(basePtr)) {
+ boxAddrOp->setAttr(cuf::getDataAttrName(), cudaAttr);
+ }
+
+ basePtr = boxAddrOp;
+ memrefTy = typeConverter.convertMemrefType(basePtr.getType());
+
+ if (baseOp) {
+ auto sameBaseBoxTypes = [&](Type baseType, Type memrefType) -> bool {
+ Type emboxBaseTy = getBaseType(baseType, true);
+ Type emboxMemrefTy = getBaseType(memrefType, true);
+ return emboxBaseTy == emboxMemrefTy;
+ };
+
+ if (auto embox = dyn_cast_or_null<fir::EmboxOp>(baseOp)) {
+ if (!sameBaseBoxTypes(embox.getType(), embox.getMemref().getType())) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: embox base type and memref type are not "
+ "the same, bailing out of conversion\n");
+ return failure();
+ }
+ if (embox.getSlice() &&
+ embox.getSlice().getDefiningOp<fir::SliceOp>()) {
+ Type originalType = embox.getMemref().getType();
+ basePtr = embox.getMemref();
+
+ if (typeConverter.convertibleMemrefType(originalType)) {
+ auto convertedMemrefTy =
+ typeConverter.convertMemrefType(originalType);
+ memrefTy = convertedMemrefTy;
+ } else {
+ return failure();
+ }
+ }
+ }
+
+ if (auto rebox = dyn_cast<fir::ReboxOp>(baseOp)) {
+ if (!sameBaseBoxTypes(rebox.getType(), rebox.getBox().getType())) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: rebox base type and box type are not the "
+ "same, bailing out of conversion\n");
+ return failure();
+ }
+ Type originalType = rebox.getBox().getType();
+ if (auto boxTy = dyn_cast<fir::BoxType>(originalType)) {
+ originalType = boxTy.getElementType();
+ }
+ if (!typeConverter.convertibleMemrefType(originalType)) {
+ return failure();
+ } else {
+ auto convertedMemrefTy =
+ typeConverter.convertMemrefType(originalType);
+ memrefTy = convertedMemrefTy;
+ }
+ }
+ }
+ }
+
+ auto convert = fir::ConvertOp::create(rewriter, loc, memrefTy, basePtr);
+ return convert->getResult(0);
+}
+
+Value FIRToMemRef::canonicalizeIndex(Value index,
+ PatternRewriter &rewriter) const {
+ if (auto blockArg = dyn_cast<BlockArgument>(index))
+ return index;
+
+ Operation *op = index.getDefiningOp();
+
+ if (auto constant = dyn_cast<arith::ConstantIntOp>(op)) {
+ if (!constant.getType().isIndex()) {
+ Value v = arith::ConstantIndexOp::create(rewriter, op->getLoc(),
+ constant.value());
+ return v;
+ }
+ return constant;
+ }
+
+ if (auto extsi = dyn_cast<arith::ExtSIOp>(op)) {
+ Value operand = extsi.getOperand();
+ if (auto indexCast = operand.getDefiningOp<arith::IndexCastOp>()) {
+ Value v = indexCast.getOperand();
+ return v;
+ }
+ return canonicalizeIndex(operand, rewriter);
+ }
+
+ if (auto add = dyn_cast<arith::AddIOp>(op)) {
+ Value lhs = canonicalizeIndex(add.getLhs(), rewriter);
+ Value rhs = canonicalizeIndex(add.getRhs(), rewriter);
+ if (lhs.getType() == rhs.getType()) {
+ return arith::AddIOp::create(rewriter, op->getLoc(), lhs, rhs);
+ }
+ }
+ return index;
+}
+
+MemRefInfo FIRToMemRef::getMemRefInfo(Value firMemref,
+ PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter,
+ Operation *memOp) {
+ Operation *memrefOp = firMemref.getDefiningOp();
+ if (!memrefOp) {
+ if (auto blockArg = dyn_cast<BlockArgument>(firMemref)) {
+ rewriter.setInsertionPoint(memOp);
+ Type memrefTy = typeConverter.convertMemrefType(blockArg.getType());
+ if (auto mt = dyn_cast<MemRefType>(memrefTy)) {
+ if (auto inner = llvm::dyn_cast<MemRefType>(mt.getElementType()))
+ memrefTy = inner;
+ }
+ Value marshal = fir::ConvertOp::create(rewriter, blockArg.getLoc(),
+ memrefTy, blockArg);
+ SmallVector<Value> indices;
+ return std::pair{marshal, indices};
+ }
+ llvm_unreachable(
+ "FIRToMemRef: expected defining op or block argument for FIR memref");
+ }
+
+ if (auto arrayCoorOp = dyn_cast<fir::ArrayCoorOp>(memrefOp)) {
+ MemRefInfo memrefInfo =
+ marshalArrayCoorOp(memOp, arrayCoorOp, rewriter, typeConverter);
+ if (succeeded(memrefInfo)) {
+ for (auto user : memrefOp->getUsers()) {
+ if (!isa<fir::LoadOp, fir::StoreOp>(user)) {
+ LLVM_DEBUG(
+ llvm::dbgs()
+ << "FIRToMemRef: array memref used by unsupported op:\n";
+ firMemref.dump(); user->dump());
+ return memrefInfo;
+ }
+ }
+ eraseOps.insert(memrefOp);
+ }
+ return memrefInfo;
+ }
+
+ rewriter.setInsertionPoint(memOp);
+
+ if (isMarshalLike(memrefOp)) {
+ FailureOr<Value> marshal =
+ getFIRMarshal(memOp, memrefOp, rewriter, typeConverter);
+ if (failed(marshal)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: expected FIR memref in marshal, bailing "
+ "out:\n";
+ firMemref.dump());
+ return failure();
+ }
+ SmallVector<Value> indices;
+ return std::pair{*marshal, indices};
+ }
+
+ if (auto declareOp = dyn_cast<fir::DeclareOp>(memrefOp)) {
+ if (memrefIsOptional(memrefOp)) {
+ rewriter.setInsertionPoint(memOp);
+ auto ifOp = memOp->getParentOfType<scf::IfOp>();
+ if (ifOp) {
+ Operation *condition = ifOp.getCondition().getDefiningOp();
+ if (condition && isa<fir::IsPresentOp>(condition)) {
+ if (condition->getOperand(0) == declareOp) {
+ if (memOp->getParentRegion() == &ifOp.getThenRegion()) {
+ rewriter.setInsertionPointToStart(
+ &(ifOp.getThenRegion().front()));
+ } else if (memOp->getParentRegion() == &ifOp.getElseRegion()) {
+ rewriter.setInsertionPointToStart(
+ &(ifOp.getElseRegion().front()));
+ }
+ }
+ }
+ }
+ }
+
+ FailureOr<Value> marshal =
+ getFIRMarshal(memOp, declareOp, rewriter, typeConverter);
+ if (failed(marshal)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: unable to create marshal for scalar "
+ "memref:\n";
+ firMemref.dump());
+ return failure();
+ }
+ SmallVector<Value> indices;
+ return std::pair{*marshal, indices};
+ }
+
+ if (auto coordinateOp = dyn_cast<fir::CoordinateOp>(memrefOp)) {
+ FailureOr<Value> marshal =
+ getFIRMarshal(memOp, coordinateOp, rewriter, typeConverter);
+ if (failed(marshal)) {
+ LLVM_DEBUG(
+ llvm::dbgs()
+ << "FIRToMemRef: unable to create marshal for derived-type "
+ "memref:\n";
+ firMemref.dump());
+ return failure();
+ }
+ SmallVector<Value> indices;
+ return std::pair{*marshal, indices};
+ }
+
+ if (auto convertOp = dyn_cast<fir::ConvertOp>(memrefOp)) {
+ Type fromTy = convertOp->getOperand(0).getType();
+ Type toTy = firMemref.getType();
+ if (isa<fir::ReferenceType>(fromTy) && isa<fir::ReferenceType>(toTy)) {
+ FailureOr<Value> marshal =
+ getFIRMarshal(memOp, convertOp, rewriter, typeConverter);
+ if (failed(marshal)) {
+ LLVM_DEBUG(
+ llvm::dbgs()
+ << "FIRToMemRef: unable to create marshal for conversion "
+ "op:\n";
+ firMemref.dump());
+ return failure();
+ }
+ SmallVector<Value> indices;
+ return std::pair{*marshal, indices};
+ }
+ }
+
+ if (auto boxAddrOp = dyn_cast<fir::BoxAddrOp>(memrefOp)) {
+ FailureOr<Value> marshal =
+ getFIRMarshal(memOp, boxAddrOp, rewriter, typeConverter);
+ if (failed(marshal)) {
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: unable to create marshal for box_addr "
+ "op:\n";
+ firMemref.dump());
+ return failure();
+ }
+ SmallVector<Value> indices;
+ return std::pair{*marshal, indices};
+ }
+
+ if (memrefIsDeviceData(memrefOp)) {
+ FailureOr<Value> marshal =
+ getFIRMarshal(memOp, memrefOp, rewriter, typeConverter);
+ if (failed(marshal))
+ return failure();
+ SmallVector<Value> indices;
+ return std::pair{*marshal, indices};
+ }
+
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: unable to create marshal for memref value:\n";
+ firMemref.dump());
+
+ return failure();
+}
+
+void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value marshal,
+ PatternRewriter &rewriter) const {
+ Operation *op = firMemref.getDefiningOp();
+ if (op && (isa<fir::ArrayCoorOp>(op) || isMarshalLike(op)))
+ return;
+
+ SmallPtrSet<Operation *, 4> worklist;
+ for (auto user : firMemref.getUsers()) {
+ if (isMarshalLike(user) || isa<fir::LoadOp, fir::StoreOp>(user))
+ continue;
+ if (!domInfo->dominates(marshal, user))
+ continue;
+
+ if (!(isa<omp::AtomicCaptureOp>(user->getParentOp()) ||
+ isa<acc::AtomicCaptureOp>(user->getParentOp()))) {
+ worklist.insert(user);
+ }
+ }
+
+ Type ty = firMemref.getType();
+
+ for (auto op : worklist) {
+ rewriter.setInsertionPoint(op);
+ Location loc = op->getLoc();
+ Value replaceConvert = fir::ConvertOp::create(rewriter, loc, ty, marshal);
+ op->replaceUsesOfWith(firMemref, replaceConvert);
+ }
+
+ worklist.clear();
+
+ for (auto user : firMemref.getUsers()) {
+ if (isMarshalLike(user) || isa<fir::LoadOp, fir::StoreOp>(user))
+ continue;
+ if (isa<omp::AtomicCaptureOp>(user->getParentOp()) ||
+ isa<acc::AtomicCaptureOp>(user->getParentOp())) {
+ if (domInfo->dominates(marshal, user))
+ worklist.insert(user);
+ }
+ }
+
+ if (worklist.empty())
+ return;
+
+ while (!worklist.empty()) {
+ Operation *parentOp = (*worklist.begin())->getParentOp();
+
+ Value replaceConvert;
+ SmallVector<Operation *> erase;
+ for (auto op : worklist) {
+ if (op->getParentOp() != parentOp)
+ continue;
+ if (!replaceConvert) {
+ rewriter.setInsertionPoint(parentOp);
+ replaceConvert =
+ fir::ConvertOp::create(rewriter, op->getLoc(), ty, marshal);
+ }
+ op->replaceUsesOfWith(firMemref, replaceConvert);
+ erase.push_back(op);
+ }
+
+ for (auto op : erase)
+ worklist.erase(op);
+ }
+}
+
+void FIRToMemRef::rewriteLoadOp(fir::LoadOp load, PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter) {
+ Value firMemref = load.getMemref();
+ if (!typeConverter.convertibleType(firMemref.getType()))
+ return;
+
+ LLVM_DEBUG(llvm::dbgs() << "FIRToMemRef: attempting to convert FIR load:\n";
+ load.dump(); firMemref.dump());
+
+ MemRefInfo memrefInfo =
+ getMemRefInfo(firMemref, rewriter, typeConverter, load.getOperation());
+ if (failed(memrefInfo))
+ return;
+
+ auto originalType = load.getResult().getType();
+ auto [marshal, indices] = *memrefInfo;
+
+ LLVM_DEBUG(llvm::dbgs()
+ << "FIRToMemRef: marshal for FIR load created successfully:\n";
+ marshal.dump());
+
+ rewriter.setInsertionPointAfter(load);
+
+ auto attr = (load.getOperation())->getAttr("tbaa");
+ auto loadOp =
+ rewriter.replaceOpWithNewOp<memref::LoadOp>(load, marshal, indices);
+ if (attr)
+ loadOp.getOperation()->setAttr("tbaa", attr);
+
+ LLVM_DEBUG(llvm::dbgs() << "FIRToMemRef: new memref.load op:\n";
+ loadOp.dump(); assert(succeeded(verify(loadOp))));
+
+ if (isa<fir::LogicalType>(originalType)) {
+ SmallVector<Operation *> loadUsers(
+ loadOp.getOperation()->getUsers().begin(),
+ loadOp.getOperation()->getUsers().end());
+ auto logicalVal =
+ fir::ConvertOp::create(rewriter, loadOp.getLoc(), originalType, loadOp);
+ for (Operation *user : loadUsers) {
+ for (auto &operand : user->getOpOperands()) {
+ if (operand.get() == loadOp)
+ operand.set(logicalVal);
+ }
+ }
+ }
+
+ if (!isa<fir::LogicalType>(originalType))
+ replaceFIRMemrefs(firMemref, marshal, rewriter);
+}
+
+void FIRToMemRef::rewriteStoreOp(fir::StoreOp store, PatternRewriter &rewriter,
+ FIRToMemRefTypeConverter &typeConverter) {
+ Value firMemref = store.getMemref();
+
+ if (!typeConverter.convertibleType(firMemref.getType()))
+ return;
+
+ LLVM_DEBUG(llvm::dbgs() << "FIRToMemRef: attempting to convert FIR store:\n";
+ store.dump(); firMemref.dump());
+
+ MemRefInfo memrefInfo =
+ getMemRefInfo(firMemref, rewriter, typeConverter, store.getOperation());
+ if (failed(memrefInfo))
+ return;
+
+ auto [marshal, indices] = *memrefInfo;
+ LLVM_DEBUG(
+ llvm::dbgs()
+ << "FIRToMemRef: marshal for FIR store created successfully:\n";
+ marshal.dump());
+
+ Value value = store.getValue();
+ rewriter.setInsertionPointAfter(store);
+
+ if (isa<fir::LogicalType>(value.getType())) {
+ auto convertedType = typeConverter.convertType(value.getType());
+ value =
+ fir::ConvertOp::create(rewriter, store.getLoc(), convertedType, value);
+ }
+
+ auto attr = (store.getOperation())->getAttr("tbaa");
+ auto storeOp = rewriter.replaceOpWithNewOp<memref::StoreOp>(store, value,
+ marshal, indices);
+ if (attr)
+ storeOp.getOperation()->setAttr("tbaa", attr);
+
+ LLVM_DEBUG(llvm::dbgs() << "FIRToMemRef: new memref.store op:\n";
+ storeOp.dump(); assert(succeeded(verify(storeOp))));
+
+ bool isLogicalRef = false;
+ if (auto refTy = llvm::dyn_cast<fir::ReferenceType>(firMemref.getType())) {
+ isLogicalRef = llvm::isa<fir::LogicalType>(refTy.getEleTy());
+ }
+ if (!isLogicalRef)
+ replaceFIRMemrefs(firMemref, marshal, rewriter);
+}
+
+void FIRToMemRef::runOnOperation() {
+ LLVM_DEBUG(llvm::dbgs() << "Enter FIRToMemRef()\n");
+
+ auto op = getOperation();
+ auto context = op.getContext();
+ auto mod = op->getParentOfType<ModuleOp>();
+ FIRToMemRefTypeConverter typeConverter(mod);
+
+ typeConverter.setConvertComplexTypes(true);
+
+ PatternRewriter rewriter(context);
+ domInfo = new DominanceInfo(op);
+
+ op.walk([&](fir::AllocaOp alloca) {
+ rewriteAlloca(alloca, rewriter, typeConverter);
+ });
+
+ op.walk([&](Operation *op) {
+ if (auto loadOp = dyn_cast<fir::LoadOp>(op)) {
+ rewriteLoadOp(loadOp, rewriter, typeConverter);
+ } else if (auto storeOp = dyn_cast<fir::StoreOp>(op)) {
+ rewriteStoreOp(storeOp, rewriter, typeConverter);
+ }
+ });
+
+ SmallVector<Operation *> worklist;
+ op->walk([&worklist](Operation *arithOp) {
+ if (llvm::isa<arith::ArithDialect>(arithOp->getDialect())) {
+ if (arithOp->use_empty()) {
+ worklist.push_back(arithOp);
+ }
+ }
+ });
+
+ while (!worklist.empty()) {
+ Operation *w = worklist.pop_back_val();
+ for (auto v : w->getOperands()) {
+ if (Operation *opnd = v.getDefiningOp()) {
+ if (llvm::isa<arith::ArithDialect>(opnd->getDialect()) &&
+ opnd->hasOneUse()) {
+ worklist.push_back(opnd);
+ }
+ }
+ }
+ assert(w->use_empty());
+ w->erase();
+ }
+
+ assert(op == getOperation());
+
+ for (auto eraseOp : eraseOps) {
+ rewriter.eraseOp(eraseOp);
+ }
+ eraseOps.clear();
+
+ if (domInfo)
+ delete domInfo;
+
+ LLVM_DEBUG(llvm::dbgs() << "After FIRToMemRef()\n"; op.dump();
+ llvm::dbgs() << "Exit FIRToMemRef()\n";);
+}
+
+} // namespace fir
diff --git a/flang/test/Fir/convert-memref-codegen.mlir b/flang/test/Fir/convert-memref-codegen.mlir
index 4496af19e0f67..5bc55647e76e1 100644
--- a/flang/test/Fir/convert-memref-codegen.mlir
+++ b/flang/test/Fir/convert-memref-codegen.mlir
@@ -1,13 +1,34 @@
-// RUN: not fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s -o - 2>&1 | FileCheck %s
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s -o - | FileCheck %s
// This test ensures that the FIR CodeGen ConvertOpConversion
-// rejects fir.convert when either the source or the destination
-// type is a memref (i.e. it fails to legalize those ops).
+// properly lowers fir.convert when either the source or the destination
+// type is a memref.
module {
- // CHECK: error: failed to legalize operation 'fir.convert'
+ // CHECK-LABEL: llvm.func @memref_to_ref_convert(
+ // Reconstruct the memref descriptor from the expanded LLVM arguments.
+ // CHECK: %[[POISON0:.*]] = llvm.mlir.poison : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[DESC0:.*]] = llvm.insertvalue %arg0, %[[POISON0]][0] : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[DESC1:.*]] = llvm.insertvalue %arg1, %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[DESC:.*]] = llvm.insertvalue %arg2, %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i64)>
+ //
+ // Lower the fir.convert from memref<f32> to !fir.ref<f32> by extracting
+ // the buffer pointer from the descriptor.
+ // CHECK: %[[ALIGNED:.*]] = llvm.extractvalue %[[DESC]][1] : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[OFF:.*]] = llvm.extractvalue %[[DESC]][2] : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[BUF:.*]] = llvm.getelementptr %[[ALIGNED]][%[[OFF]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
+ //
+ // The second fir.convert (from !fir.ref<f32> back to memref<f32>) lowering
+ // CHECK: %[[POISON1:.*]] = llvm.mlir.poison : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[DESC2:.*]] = llvm.insertvalue %[[BUF]], %[[POISON1]][0] : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[DESC3:.*]] = llvm.insertvalue %[[BUF]], %[[DESC2]][1] : !llvm.struct<(ptr, ptr, i64)>
+ // CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : index) : i64
+ // CHECK: %[[DESC4:.*]] = llvm.insertvalue %[[ZERO]], %[[DESC3]][2] : !llvm.struct<(ptr, ptr, i64)>
+ //
+ // CHECK-NOT: fir.convert
func.func @memref_to_ref_convert(%arg0: memref<f32>) {
%0 = fir.convert %arg0 : (memref<f32>) -> !fir.ref<f32>
+ %1 = fir.convert %0 : (!fir.ref<f32>) -> memref<f32>
return
}
}
diff --git a/flang/test/Transforms/FIRToMemRef/alloca.mlir b/flang/test/Transforms/FIRToMemRef/alloca.mlir
new file mode 100644
index 0000000000000..a60ea6354a45d
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/alloca.mlir
@@ -0,0 +1,97 @@
+// Test conversions of fir.alloca
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// Test that compiler generated fir.allocas are converted, slightly edited from
+// subroutine alloca(a)
+// call f(1)
+// end
+
+// CHECK-LABEL: func.func @alloca
+// CHECK: [[ALLOCA:%.+]] = memref.alloca() : memref<i32>
+// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK: [[CONSTANT:%.+]] = arith.constant 1 : i32
+// CHECK: memref.store [[CONSTANT]], [[ALLOCA]][] : memref<i32>
+// CHECK: fir.call @f([[MARSHAL0]])
+
+func.func @alloca(%arg0: !fir.ref<f32> {fir.bindc_name = "a"}) {
+ %0 = fir.alloca i32 {adapt.valuebyref}
+ %c1_i32 = arith.constant 1 : i32
+ %1 = fir.dummy_scope : !fir.dscope
+ %2 = fir.declare %arg0 dummy_scope %1 {uniq_name = "alloca"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ fir.store %c1_i32 to %0 : !fir.ref<i32>
+ %false = arith.constant false
+ fir.call @f(%0) fastmath<contract> : (!fir.ref<i32>) -> ()
+ return
+}
+func.func private @f(!fir.ref<i32>)
+
+// Test that compiler generated fir.allocas are converted, slightly edited from
+// subroutine passbyvalue(x)
+// integer, value :: x
+// end subroutine
+
+// CHECK-LABEL: func.func @passbyvalue
+// CHECK: [[ALLOCA:%.+]] = memref.alloca() : memref<i32>
+// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: memref.store %arg0, [[ALLOCA]][] : memref<i32>
+
+func.func @passbyvalue(%arg0: i32 {fir.bindc_name = "x"}) {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.alloca i32
+ fir.store %arg0 to %1 : !fir.ref<i32>
+ %2 = fir.declare %1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFpEx"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ return
+}
+
+// Multi-dim dynamic alloca, reduced from
+// subroutine alloca_2d(n,m)
+// real :: a(n,m)
+// end
+
+// CHECK-LABEL: func.func @_QPalloca_2d
+// CHECK: [[CON5:%.+]] = arith.constant 5
+// CHECK-NEXT: [[CON3:%.+]] = arith.constant 3
+// CHECK-NEXT: [[ALLOCA:%.+]] = memref.alloca([[CON3]], [[CON5]]) {bindc_name = "a"} : memref<?x?xf32>
+// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<?x?xf32>) -> !fir.ref<!fir.array<?x?xf32>>
+
+func.func @_QPalloca_2d() {
+ %0 = arith.constant 5 : index
+ %1 = arith.constant 3 : index
+ %2 = fir.alloca !fir.array<?x?xf32>, %0, %1 {bindc_name = "a"}
+ return
+}
+
+// CHECK-LABEL: func.func @alloca_nonconvertible
+// CHECK-NEXT: [[ALLOCA1:%.+]] = fir.alloca
+// CHECK-NEXT: [[ALLOCA2:%.+]] = memref.alloca
+// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA2]] : (memref<i32>) -> !fir.ref<i32>
+func.func @alloca_nonconvertible() {
+ %0 = fir.alloca !fir.box<!fir.array<20xi32>>
+ %1 = fir.alloca i32
+ return
+}
+
+// CHECK-LABEL: func.func @peep_declare
+// CHECK: [[ALLOCA:%.+]] = memref.alloca() : memref<i32>
+// CHECK-NOT: fircg.ext_declare
+// CHECK: memref.store %c1_i32, [[ALLOCA]][] : memref<i32>
+func.func @peep_declare() {
+ %c1_i32 = arith.constant 1 : i32
+ %0 = fir.alloca i32
+ %1 = fir.declare %0 {uniq_name = "some_name"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ fir.store %c1_i32 to %1 : !fir.ref<i32>
+ return
+}
+
+
+// check that attributes are copied when they exist
+// CHECK-LABEL: func.func @no_peep_declare
+// CHECK: memref.alloca() {bindc_name = "x", uniq_name = "y"} : memref<i32>
+// CHECK-NOT: memref.store %c1_i32, %alloca[] : memref<i32>
+func.func @no_peep_declare() {
+ %c1_i32 = arith.constant 1 : i32
+ %0 = fir.alloca i32 {bindc_name = "x", uniq_name = "y"}
+ %1 = fir.declare %0 {uniq_name = "some_name"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ fir.store %c1_i32 to %1 : !fir.ref<i32>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir b/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir
new file mode 100644
index 0000000000000..4ad3e045ac653
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir
@@ -0,0 +1,47 @@
+// Test conversions to index
+// Test dynamically legal array coor ops, we should both keep a fir.array_coor
+// and generate a memref.store
+// example fortran code:
+// subroutine func(a)
+// integer :: a(4)
+// end
+//
+// subroutine slice(a)
+// integer :: a(8)
+// call func(a(1:4))
+// a(5) = 1
+// a(1) = 2
+// end
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @slice
+// CHECK: [[C5:%.+]] = arith.constant 5 : index
+// CHECK: [[C1_I32:%.+]] = arith.constant 1 : i32
+// CHECK: [[C1:%.+]] = arith.constant 1 : index
+// CHECK: [[C8:%.+]] = arith.constant 8 : index
+// CHECK: [[DUMMY:%.+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[SHAPE:%.+]] = fir.shape [[C8]] : (index) -> !fir.shape<1>
+// CHECK: [[DECLARE:%.+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]]
+// CHECK: [[COOR1:%.+]] = fir.array_coor [[DECLARE]]([[SHAPE]]) [[C1]] : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+// CHECK: [[SLICE:%.+]] = fir.convert [[COOR1]] : (!fir.ref<i32>) -> !fir.ref<!fir.array<4xi32>>
+// CHECK: [[MARSHAL:%.+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<8xi32>>) -> memref<8xi32>
+// CHECK: [[C1B:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB:%.+]] = arith.subi [[C5]], [[C1B]] : index
+// CHECK: [[MUL:%.+]] = arith.muli [[SUB]], [[C1B]] : index
+// CHECK: [[SUB2:%.+]] = arith.subi [[C1B]], [[C1B]] : index
+// CHECK: [[IDX:%.+]] = arith.addi [[MUL]], [[SUB2]] : index
+// CHECK: memref.store [[C1_I32]], [[MARSHAL]][[[IDX]]] : memref<8xi32>
+func.func @slice(%arg0: !fir.ref<!fir.array<8xi32>>){
+ %c5 = arith.constant 5 : index
+ %c1_i32 = arith.constant 1 : i32
+ %c1 = arith.constant 1 : index
+ %c8 = arith.constant 8 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.shape %c8 : (index) -> !fir.shape<1>
+ %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFsliceEa"} : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<8xi32>>
+ %3 = fir.array_coor %2(%1) %c1 : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ %4 = fir.convert %3 : (!fir.ref<i32>) -> !fir.ref<!fir.array<4xi32>>
+ %5 = fir.array_coor %2(%1) %c5 : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c1_i32 to %5 : !fir.ref<i32>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/complex.mlir b/flang/test/Transforms/FIRToMemRef/complex.mlir
new file mode 100644
index 0000000000000..738d1b7f4ea08
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/complex.mlir
@@ -0,0 +1,18 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @convert_complex_
+// CHECK: [[DECL0:%[0-9]+]] = fir.declare %arg0
+// CHECK: [[DECL1:%[0-9]+]] = fir.declare %arg1
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[DECL1]] : (!fir.ref<complex<f32>>) -> memref<complex<f32>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL1]][] : memref<complex<f32>>
+// CHECK: [[MARSHAL0:%[0-9]+]] = fir.convert [[DECL0]] : (!fir.ref<complex<f32>>) -> memref<complex<f32>>
+// CHECK: memref.store [[LOAD]], [[MARSHAL0]][] : memref<complex<f32>>
+
+func.func @convert_complex_(%arg0: !fir.ref<complex<f32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<complex<f32>> {fir.bindc_name = "b"}) attributes {fir.internal_name = "_QPconvert_complex"} {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "_QFconvert_complexEa"} : (!fir.ref<complex<f32>>, !fir.dscope) -> !fir.ref<complex<f32>>
+ %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFconvert_complexEb"} : (!fir.ref<complex<f32>>, !fir.dscope) -> !fir.ref<complex<f32>>
+ %3 = fir.load %2 : !fir.ref<complex<f32>>
+ fir.store %3 to %1 : !fir.ref<complex<f32>>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/cuda-alloca.mlir b/flang/test/Transforms/FIRToMemRef/cuda-alloca.mlir
new file mode 100644
index 0000000000000..d42350728016a
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/cuda-alloca.mlir
@@ -0,0 +1,14 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK: memref.alloca() {cuf.data_attr = #cuf.cuda<device>} : memref<i32>
+// CHECK-NOT: fir.load
+// CHECK-NOT: fir.store
+
+func.func @cuf_alloca_(%arg0: !fir.ref<i32> {fir.bindc_name = "r"}) {
+ %c0_i32 = arith.constant 0 : i32
+ %0 = fir.alloca i32 {cuf.data_attr = #cuf.cuda<device>}
+ fir.store %c0_i32 to %0 : !fir.ref<i32>
+ %1 = fir.load %0 : !fir.ref<i32>
+ fir.store %1 to %arg0 : !fir.ref<i32>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/derived-types.mlir b/flang/test/Transforms/FIRToMemRef/derived-types.mlir
new file mode 100644
index 0000000000000..0bcf926c4bdca
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/derived-types.mlir
@@ -0,0 +1,31 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @load_scalar
+// CHECK: [[INDEX:%[0-9]]] = fir.field_index
+// CHECK: [[COORD:%[0-9]]] = fir.coordinate_of
+// CHECK-NEXT: [[MARSHAL:%[0-9]]] = fir.convert [[COORD]] : (!fir.ref<f32>) -> memref<f32>
+// CHECK-NEXT: memref.load [[MARSHAL]][] : memref<f32>
+func.func @load_scalar(%arg0: !fir.ref<!fir.type<DerivedType{a:f32}>>) {
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "dtype"} : (!fir.ref<!fir.type<DerivedType{a:f32}>>, !fir.dscope) -> !fir.ref<!fir.type<DerivedType{a:f32}>>
+ %2 = fir.field_index a, !fir.type<DerivedType{a:f32}>
+ %3 = fir.coordinate_of %1, %2 : (!fir.ref<!fir.type<DerivedType{a:f32}>>, !fir.field) -> !fir.ref<f32>
+ %4 = fir.load %3 : !fir.ref<f32>
+ return
+}
+
+// CHECK-LABEL: func.func @store_scalar
+// CHECK: [[INDEX:%[0-9]]] = fir.field_index
+// CHECK: [[COORD:%[0-9]]] = fir.coordinate_of
+// CHECK-NEXT: [[MARSHAL:%[0-9]]] = fir.convert [[COORD]] : (!fir.ref<f32>) -> memref<f32>
+// CHECK-NEXT: memref.store %4, [[MARSHAL]][] : memref<f32>
+func.func @store_scalar(%arg0: !fir.ref<!fir.type<DerivedType{a:f32}>>, %arg1: !fir.ref<f32>) {
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "dtype"} : (!fir.ref<!fir.type<DerivedType{a:f32}>>, !fir.dscope) -> !fir.ref<!fir.type<DerivedType{a:f32}>>
+ %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "x"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %3 = fir.load %2 : !fir.ref<f32>
+ %4 = fir.field_index a, !fir.type<DerivedType{a:f32}>
+ %5 = fir.coordinate_of %1, %4 : (!fir.ref<!fir.type<DerivedType{a:f32}>>, !fir.field) -> !fir.ref<f32>
+ fir.store %3 to %5 : !fir.ref<f32>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/index.mlir b/flang/test/Transforms/FIRToMemRef/index.mlir
new file mode 100644
index 0000000000000..aa33890d6b70e
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/index.mlir
@@ -0,0 +1,31 @@
+// Test conversions to index
+
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @load_array1d_var
+// CHECK: [[C3:%.+]] = arith.constant 3 : index
+// CHECK: [[DUMMY:%.+]] = fir.undefined !fir.dscope
+// CHECK: [[SHAPE:%.+]] = fir.shape [[C3]] : (index) -> !fir.shape<1>
+// CHECK: [[DECLARE0:%.+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]]
+// CHECK: [[DECLARE1:%.+]] = fir.declare %arg1 dummy_scope [[DUMMY]]
+// CHECK: [[MARSHAL1:%.+]] = fir.convert [[DECLARE1]] : (!fir.ref<i64>) -> memref<i64>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL1]][] : memref<i64>
+// CHECK: [[MARSHAL0:%.+]] = fir.convert [[DECLARE0]] : (!fir.ref<!fir.array<3xf32>>) -> memref<3xf32>
+// CHECK: [[C1:%.+]] = arith.constant 1 : index
+// CHECK-NEXT: [[CAST:%[0-9]+]] = arith.index_cast [[LOAD]] : i64 to index
+// CHECK-NEXT: [[SUB:%.+]] = arith.subi [[CAST]], [[C1]] : index
+// CHECK-NEXT: [[MUL:%.+]] = arith.muli [[SUB]], [[C1]] : index
+// CHECK-NEXT: [[SUBA:%.+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK-NEXT: [[ADD:%.+]] = arith.addi [[MUL]], [[SUBA]] : index
+// CHECK-NEXT: memref.load [[MARSHAL0]][[[ADD]]] : memref<3xf32>
+func.func @load_array1d_var(%arg0: !fir.ref<!fir.array<3xf32>>, %arg1: !fir.ref<i64>) {
+ %c3 = arith.constant 3 : index
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c3 : (index) -> !fir.shape<1>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<3xf32>>
+ %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "i"} : (!fir.ref<i64>, !fir.dscope) -> !fir.ref<i64>
+ %3 = fir.load %2 : !fir.ref<i64>
+ %4 = fir.array_coor %1(%shape) %3 : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, i64) -> !fir.ref<f32>
+ %5 = fir.load %4 : !fir.ref<f32>
+ return
+}
\ No newline at end of file
diff --git a/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir b/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir
new file mode 100644
index 0000000000000..0b48898a1bbe6
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir
@@ -0,0 +1,130 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// subroutine load_descriptor(x)
+// real, dimension(:) :: x
+// real :: y
+// y = x(9)
+// end subroutine load_descriptor
+// CHECK-LABEL: func.func @load_descriptor
+// CHECK: [[CONST9:%.+]] = arith.constant 9 : index
+// CHECK: [[DUMMY:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST9]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[ELSIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> index
+// CHECK: [[CONST0:%.+]] = arith.constant 0 : index
+// CHECK: [[DIMS:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV:%[0-9]+]] = arith.divsi [[DIMS]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0_0:%.+]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_0]]], sizes: [[[DIMS]]#1], strides: [[[DIV]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET]][[[ADD1]]] : memref<?xf32, strided<[?], offset: ?>>
+func.func @load_descriptor(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+ %c9 = arith.constant 9 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+ %2 = fir.rebox %1 : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+ %5 = fir.array_coor %2 %c9 : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
+
+
+// subroutine load_dynamic_2d(x)
+// real, dimension(:, :) :: x
+// real :: y
+// y = x(9, 3)
+// end subroutine load_dynamic_2d
+// CHECK-LABEL: func.func @load_dynamic_2d
+// CHECK: [[CONST3:%.+]] = arith.constant 3 : index
+// CHECK: [[CONST9:%.+]] = arith.constant 9 : index
+// CHECK: [[DUMMY:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "_QFload_static_1dEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST9]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi [[CONST3]], [[CONST1]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[CONST1]] : index
+// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
+// CHECK: [[ELSIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> index
+// CHECK: [[CONST1_0:%.+]] = arith.constant 1 : index
+// CHECK: [[DIMS1:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST1_0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV1:%[0-9]+]] = arith.divsi [[DIMS1]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0:%.+]] = arith.constant 0 : index
+// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0_1:%.+]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_1]]], sizes: [[[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV1]], [[DIV0]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET]][[[ADD2]], [[ADD1]]] : memref<?x?xf32, strided<[?, ?], offset: ?>>
+func.func @load_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) {
+ %c3 = arith.constant 3 : index
+ %c9 = arith.constant 9 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "_QFload_static_1dEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
+ %2 = fir.rebox %1 : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+ %5 = fir.array_coor %2 %c9, %c3 : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
+
+
+// subroutine load_dynamic_3d(x)
+// real, dimension(:,:,:) :: x
+// real :: y
+// y = x(2,2,3)
+// end subroutine load_dynamic_3d
+// CHECK-LABEL: func.func @load_dynamic_3d
+// CHECK: [[CONST3:%.+]] = arith.constant 3 : index
+// CHECK: [[CONST2:%.+]] = arith.constant 2 : index
+// CHECK: [[DUMMY:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.box<!fir.array<?x?x?xf32>>
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[CONST1]] : index
+// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
+// CHECK: [[SUB3:%[0-9]+]] = arith.subi [[CONST3]], [[CONST1]] : index
+// CHECK: [[MUL3:%[0-9]+]] = arith.muli [[SUB3]], [[CONST1]] : index
+// CHECK: [[SUB3A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD3:%[0-9]+]] = arith.addi [[MUL3]], [[SUB3A]] : index
+// CHECK: [[ELSIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> index
+// CHECK: [[CONST2_0:%.+]] = arith.constant 2 : index
+// CHECK: [[DIMS2:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST2_0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV2:%[0-9]+]] = arith.divsi [[DIMS2]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST1_1:%.+]] = arith.constant 1 : index
+// CHECK: [[DIMS1:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST1_1]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV1:%[0-9]+]] = arith.divsi [[DIMS1]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0:%.+]] = arith.constant 0 : index
+// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0_2:%.+]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_2]]], sizes: [[[DIMS2]]#1, [[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV2]], [[DIV1]], [[DIV0]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+func.func @load_dynamic_3d(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "x"}) {
+ %c3 = arith.constant 3 : index
+ %c2 = arith.constant 2 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
+ %2 = fir.rebox %1 : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.box<!fir.array<?x?x?xf32>>
+ %5 = fir.array_coor %2 %c2, %c2, %c3 : (!fir.box<!fir.array<?x?x?xf32>>, index, index, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
\ No newline at end of file
diff --git a/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir b/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir
new file mode 100644
index 0000000000000..9a12c1d4fc011
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir
@@ -0,0 +1,169 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// test fir.shift op
+// derived from:
+// subroutine load_shift_1d(x, y)
+// !generate fir.shift
+// real, dimension(2:) :: x
+// !fir.shape_shift
+// !real, dimension(2:10) :: x
+// real :: y
+// y = x(6)
+// end subroutine load_shift_1d
+// CHECK-LABEL: func.func @load_shift_1d
+// CHECK: [[C6:%.*]] = arith.constant 6 : index
+// CHECK: [[C2_I64:%.*]] = arith.constant 2 : i64
+// CHECK: [[DUMMY_SCOPE:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[INDEX_CAST:%[0-9]+]] = arith.index_cast [[C2_I64]] : i64 to index
+// CHECK: [[SHIFT:%[0-9]+]] = fir.shift [[INDEX_CAST]] : (index) -> !fir.shift<1>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHIFT]]) dummy_scope [[DUMMY_SCOPE]] {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]]([[SHIFT]]) : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>) -> !fir.box<!fir.array<?xf32>>
+// CHECK: [[BOX_ADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI:%[0-9]+]] = arith.subi [[C6]], [[C1]] : index
+// CHECK: [[MULI:%[0-9]+]] = arith.muli [[SUBI]], [[C1]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADDI:%[0-9]+]] = arith.addi [[MULI]], [[SUBI2]] : index
+// CHECK: [[BOX_ELESIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> index
+// CHECK: [[C0:%.*]] = arith.constant 0 : index
+// CHECK: [[BOX_DIMS:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIVSI:%[0-9]+]] = arith.divsi [[BOX_DIMS]]#2, [[BOX_ELESIZE]] : index
+// CHECK: [[C0_0:%.*]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[C0_0]]], sizes: [[[BOX_DIMS]]#1], strides: [[[DIVSI]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET_CAST]][[[ADDI]]] : memref<?xf32, strided<[?], offset: ?>>
+func.func @load_shift_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+ %c6 = arith.constant 6 : index
+ %c2_i64 = arith.constant 2 : i64
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = arith.index_cast %c2_i64 : i64 to index
+ %2 = fir.shift %1 : (index) -> !fir.shift<1>
+ %3 = fir.declare %arg0(%2) dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+ %4 = fir.rebox %3(%2) : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>) -> !fir.box<!fir.array<?xf32>>
+ %5 = fir.array_coor %4 %c6 : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
+
+// test fir.shift op for 2D array
+// derived from:
+// subroutine load_shift_2d(x, y)
+// real, dimension(2:,3:) :: x
+// !real, dimension(2:10,3:10) :: x
+// real :: y
+// y = x(6,7)
+// end subroutine load_shift_2d
+// CHECK-LABEL: func.func @load_shift_2d
+// CHECK: [[C7:%.*]] = arith.constant 7 : index
+// CHECK: [[C6:%.*]] = arith.constant 6 : index
+// CHECK: [[C3_I64:%.*]] = arith.constant 3 : i64
+// CHECK: [[C2_I64:%.*]] = arith.constant 2 : i64
+// CHECK: [[DUMMY_SCOPE:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[INDEX_CAST1:%[0-9]+]] = arith.index_cast [[C2_I64]] : i64 to index
+// CHECK: [[INDEX_CAST2:%[0-9]+]] = arith.index_cast [[C3_I64]] : i64 to index
+// CHECK: [[SHIFT:%[0-9]+]] = fir.shift [[INDEX_CAST1]], [[INDEX_CAST2]] : (index, index) -> !fir.shift<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHIFT]]) dummy_scope [[DUMMY_SCOPE]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]]([[SHIFT]]) : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK: [[BOX_ADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C6]], [[INDEX_CAST1]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[INDEX_CAST1]], [[INDEX_CAST1]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[SUBI3:%[0-9]+]] = arith.subi [[C7]], [[INDEX_CAST2]] : index
+// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1]] : index
+// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[INDEX_CAST2]], [[INDEX_CAST2]] : index
+// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
+// CHECK: [[BOX_ELESIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> index
+// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
+// CHECK: [[BOX_DIMS1:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C1_0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIVSI1:%[0-9]+]] = arith.divsi [[BOX_DIMS1]]#2, [[BOX_ELESIZE]] : index
+// CHECK: [[C0:%.*]] = arith.constant 0 : index
+// CHECK: [[BOX_DIMS2:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIVSI2:%[0-9]+]] = arith.divsi [[BOX_DIMS2]]#2, [[BOX_ELESIZE]] : index
+// CHECK: [[C0_1:%.*]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[C0_1]]], sizes: [[[BOX_DIMS1]]#1, [[BOX_DIMS2]]#1], strides: [[[DIVSI1]], [[DIVSI2]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET_CAST]][[[ADDI2]], [[ADDI1]]] : memref<?x?xf32, strided<[?, ?], offset: ?>>
+func.func @load_shift_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) {
+ %c7 = arith.constant 7 : index
+ %c6 = arith.constant 6 : index
+ %c3_i64 = arith.constant 3 : i64
+ %c2_i64 = arith.constant 2 : i64
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = arith.index_cast %c2_i64 : i64 to index
+ %2 = arith.index_cast %c3_i64 : i64 to index
+ %3 = fir.shift %1, %2 : (index, index) -> !fir.shift<2>
+ %4 = fir.declare %arg0(%3) dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
+ %5 = fir.rebox %4(%3) : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?xf32>>
+ %7 = fir.array_coor %5(%3) %c6, %c7 : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, index, index) -> !fir.ref<f32>
+ %8 = fir.load %7 : !fir.ref<f32>
+ return
+}
+
+// test fir.shift op for 3D array
+// derived from:
+// subroutine load_shift_3d(x, y)
+// real, dimension(2:,1:,3:) :: x
+// !real, dimension(2:10,1:10,3:10) :: x
+// real :: y
+// y = x(9,10,9)
+// end subroutine load_shift_3d
+// CHECK-LABEL: func.func @load_shift_3d
+// CHECK: [[C10:%.*]] = arith.constant 10 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[C3_I64:%.*]] = arith.constant 3 : i64
+// CHECK: [[C1_I64:%.*]] = arith.constant 1 : i64
+// CHECK: [[C2_I64:%.*]] = arith.constant 2 : i64
+// CHECK: [[DUMMY_SCOPE:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[INDEX_CAST1:%[0-9]+]] = arith.index_cast [[C2_I64]] : i64 to index
+// CHECK: [[INDEX_CAST2:%[0-9]+]] = arith.index_cast [[C1_I64]] : i64 to index
+// CHECK: [[INDEX_CAST3:%[0-9]+]] = arith.index_cast [[C3_I64]] : i64 to index
+// CHECK: [[SHIFT:%[0-9]+]] = fir.shift [[INDEX_CAST1]], [[INDEX_CAST2]], [[INDEX_CAST3]] : (index, index, index) -> !fir.shift<3>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHIFT]]) dummy_scope [[DUMMY_SCOPE]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]]([[SHIFT]]) : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>) -> !fir.box<!fir.array<?x?x?xf32>>
+// CHECK: [[BOX_ADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[INDEX_CAST1]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[INDEX_CAST1]], [[INDEX_CAST1]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[SUBI3:%[0-9]+]] = arith.subi [[C10]], [[INDEX_CAST2]] : index
+// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1]] : index
+// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[INDEX_CAST2]], [[INDEX_CAST2]] : index
+// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
+// CHECK: [[SUBI5:%[0-9]+]] = arith.subi [[C9]], [[INDEX_CAST3]] : index
+// CHECK: [[MULI3:%[0-9]+]] = arith.muli [[SUBI5]], [[C1]] : index
+// CHECK: [[SUBI6:%[0-9]+]] = arith.subi [[INDEX_CAST3]], [[INDEX_CAST3]] : index
+// CHECK: [[ADDI3:%[0-9]+]] = arith.addi [[MULI3]], [[SUBI6]] : index
+// CHECK: [[BOX_ELESIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> index
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[BOX_DIMS1:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C2]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIVSI1:%[0-9]+]] = arith.divsi [[BOX_DIMS1]]#2, [[BOX_ELESIZE]] : index
+// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
+// CHECK: [[BOX_DIMS2:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C1_0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIVSI2:%[0-9]+]] = arith.divsi [[BOX_DIMS2]]#2, [[BOX_ELESIZE]] : index
+// CHECK: [[C0:%.*]] = arith.constant 0 : index
+// CHECK: [[BOX_DIMS3:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIVSI3:%[0-9]+]] = arith.divsi [[BOX_DIMS3]]#2, [[BOX_ELESIZE]] : index
+// CHECK: [[C0_1:%.*]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[C0_1]]], sizes: [[[BOX_DIMS1]]#1, [[BOX_DIMS2]]#1, [[BOX_DIMS3]]#1], strides: [[[DIVSI1]], [[DIVSI2]], [[DIVSI3]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET_CAST]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+func.func @load_shift_3d(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "x"}) {
+ %c10 = arith.constant 10 : index
+ %c9 = arith.constant 9 : index
+ %c3_i64 = arith.constant 3 : i64
+ %c1_i64 = arith.constant 1 : i64
+ %c2_i64 = arith.constant 2 : i64
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = arith.index_cast %c2_i64 : i64 to index
+ %2 = arith.index_cast %c1_i64 : i64 to index
+ %3 = arith.index_cast %c3_i64 : i64 to index
+ %4 = fir.shift %1, %2, %3 : (index, index, index) -> !fir.shift<3>
+ %5 = fir.declare %arg0(%4) dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
+ %6 = fir.rebox %5(%4) : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>) -> !fir.box<!fir.array<?x?x?xf32>>
+ %8 = fir.array_coor %6(%4) %c9, %c10, %c9 : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>, index, index, index) -> !fir.ref<f32>
+ %9 = fir.load %8 : !fir.ref<f32>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir b/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir
new file mode 100644
index 0000000000000..71b6b29fe451e
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir
@@ -0,0 +1,114 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// Test for load_shift_1d function
+// CHECK-LABEL: func.func @load_shift_1d
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {uniq_name = "x"} : memref<9xf32>
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<9xf32>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]] : (index, index) -> !fir.shapeshift<1>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9xf32>>) -> memref<9xf32>
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADDI1]]] : memref<9xf32>
+func.func @load_shift_1d() {
+ %c2 = arith.constant 2 : index
+ %c9 = arith.constant 9 : index
+ %0 = fir.alloca !fir.array<9xf32> {uniq_name = "x"}
+ %1 = fir.shape_shift %c2, %c9 : (index, index) -> !fir.shapeshift<1>
+ %2 = fir.declare %0(%1) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
+ %5 = fir.array_coor %2(%1) %c9 : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
+
+// subroutine load_shift_2d()
+// real, dimension(2:10,1:10) :: x
+// real :: y
+// y = x(9,10)
+// end subroutine load_shift_2d
+// Test for load_shift_2d function
+// CHECK-LABEL: func.func @load_shift_2d
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[C10:%.*]] = arith.constant 10 : index
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {uniq_name = "x"} : memref<10x9xf32>
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<10x9xf32>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]] : (index, index, index, index) -> !fir.shapeshift<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFload_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10xf32>>) -> memref<10x9xf32>
+// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[SUBI3:%[0-9]+]] = arith.subi [[C10]], [[C1]] : index
+// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1_0]] : index
+// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADDI2]], [[ADDI1]]] : memref<10x9xf32>
+func.func @load_shift_2d(){
+ %c2 = arith.constant 2 : index
+ %c9 = arith.constant 9 : index
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.array<9x10xf32> {uniq_name = "x"}
+ %1 = fir.shape_shift %c2, %c9, %c1, %c10 : (index, index, index, index) -> !fir.shapeshift<2>
+ %2 = fir.declare %0(%1) {uniq_name = "_QFload_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
+ %5 = fir.array_coor %2(%1) %c9, %c10 : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>, index, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
+
+// subroutine load_shift_3d()
+// real, dimension(2:10,1:10, 3:10) :: x
+// real :: y
+// y = x(9,10,9)
+// end subroutine load_shift_3d
+// CHECK-LABEL: func.func @load_shift_3d
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[C10:%.*]] = arith.constant 10 : index
+// CHECK: [[C3:%.*]] = arith.constant 3 : index
+// CHECK: [[C8:%.*]] = arith.constant 8 : index
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "x"} : memref<8x10x9xf32>
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<8x10x9xf32>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]], [[C3]], [[C8]] : (index, index, index, index, index, index) -> !fir.shapeshift<3>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFload_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10x8xf32>>) -> memref<8x10x9xf32>
+// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[SUBI3:%[0-9]+]] = arith.subi [[C10]], [[C1]] : index
+// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1_0]] : index
+// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
+// CHECK: [[SUBI5:%[0-9]+]] = arith.subi [[C9]], [[C3]] : index
+// CHECK: [[MULI3:%[0-9]+]] = arith.muli [[SUBI5]], [[C1_0]] : index
+// CHECK: [[SUBI6:%[0-9]+]] = arith.subi [[C3]], [[C3]] : index
+// CHECK: [[ADDI3:%[0-9]+]] = arith.addi [[MULI3]], [[SUBI6]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<8x10x9xf32>
+func.func @load_shift_3d() {
+ %c2 = arith.constant 2 : index
+ %c9 = arith.constant 9 : index
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ %c3 = arith.constant 3 : index
+ %c8 = arith.constant 8 : index
+ %0 = fir.alloca !fir.array<9x10x8xf32> {bindc_name = "x", uniq_name = "x"}
+ %1 = fir.shape_shift %c2, %c9, %c1, %c10, %c3, %c8 : (index, index, index, index, index, index) -> !fir.shapeshift<3>
+ %2 = fir.declare %0(%1) {uniq_name = "_QFload_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
+ %5 = fir.array_coor %2(%1) %c9, %c10, %c9 : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>, index, index, index) -> !fir.ref<f32>
+ %6 = fir.load %5 : !fir.ref<f32>
+ return
+}
+
+
diff --git a/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir b/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir
new file mode 100644
index 0000000000000..bc351a7dd2f4e
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir
@@ -0,0 +1,70 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @load_scalar
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<f32>) -> memref<f32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][] : memref<f32>
+func.func @load_scalar(%arg0: !fir.ref<f32>) {
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "a"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %2 = fir.load %1 : !fir.ref<f32>
+ return
+}
+
+
+// CHECK-LABEL: func.func @load_array1d_const
+// CHECK: [[C1:%.+]] = arith.constant 1 : index
+// CHECK: [[C3:%.+]] = arith.constant 3 : index
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape [[C3]] : (index) -> !fir.shape<1>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<3xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3xf32>>) -> memref<3xf32>
+// CHECK: [[C1_0:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB:%[0-9]+]] = arith.subi [[C1]], [[C1_0]] : index
+// CHECK: [[MUL:%[0-9]+]] = arith.muli [[SUB]], [[C1_0]] : index
+// CHECK: [[SUBA:%[0-9]+]] = arith.subi [[C1_0]], [[C1_0]] : index
+// CHECK: [[ADD:%[0-9]+]] = arith.addi [[MUL]], [[SUBA]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD]]] : memref<3xf32>
+func.func @load_array1d_const(%arg0: !fir.ref<!fir.array<3xf32>>) {
+ %c1 = arith.constant 1 : index
+ %c3 = arith.constant 3 : index
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c3 : (index) -> !fir.shape<1>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<3xf32>>
+ %2 = fir.array_coor %1(%shape) %c1 : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+ %3 = fir.load %2 : !fir.ref<f32>
+ return
+}
+
+// CHECK-LABEL: func.func @load_array2d_const
+// CHECK: [[C2:%.+]] = arith.constant 2 : index
+// CHECK: [[C3:%.+]] = arith.constant 3 : index
+// CHECK: [[C6:%.+]] = arith.constant 6 : index
+// CHECK: [[C5:%.+]] = arith.constant 5 : index
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape [[C5]], [[C6]] : (index, index) -> !fir.shape<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<!fir.array<5x6xf32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x6xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x6xf32>>) -> memref<6x5xf32>
+// CHECK: [[C1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[C2]], [[C1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[C1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi [[C3]], [[C1]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[C1]] : index
+// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD2]], [[ADD1]]] : memref<6x5xf32>
+func.func @load_array2d_const(%arg0: !fir.ref<!fir.array<5x6xf32>>) {
+ %c2 = arith.constant 2 : index
+ %c3 = arith.constant 3 : index
+ %c6 = arith.constant 6 : index
+ %c5 = arith.constant 5 : index
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c5, %c6 : (index, index) -> !fir.shape<2>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} : (!fir.ref<!fir.array<5x6xf32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x6xf32>>
+ %2 = fir.array_coor %1(%shape) %c2, %c3 : (!fir.ref<!fir.array<5x6xf32>>, !fir.shape<2>, index, index) -> !fir.ref<f32>
+ %3 = fir.load %2 : !fir.ref<f32>
+ return
+}
\ No newline at end of file
diff --git a/flang/test/Transforms/FIRToMemRef/logical.mlir b/flang/test/Transforms/FIRToMemRef/logical.mlir
new file mode 100644
index 0000000000000..2c0fdb7b2379a
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/logical.mlir
@@ -0,0 +1,30 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+// CHECK-LABEL: func.func @load_scalar
+// CHECK: [[DUMMY:%0]] = fir.undefined !fir.dscope
+// CHECK-NEXT: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]]
+// CHECK-NEXT: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.logical<4>>) -> memref<i32>
+// CHECK-NEXT: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][] : memref<i32>
+// CHECK-NEXT: fir.convert [[LOAD]] : (i32) -> !fir.logical<4>
+func.func @load_scalar(%arg0: !fir.ref<!fir.logical<4>>) {
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "a"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>>
+ %2 = fir.load %1 : !fir.ref<!fir.logical<4>>
+ return
+}
+
+// CHECK-LABEL: func.func @store_scalar
+// CHECK: [[CONSTTRUE:%.+]] = arith.constant true
+// CHECK: [[DUMMY:%0]] = fir.undefined !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]]
+// CHECK-NEXT: [[CONVERT:%[0-9]+]] = fir.convert [[CONSTTRUE]] : (i1) -> !fir.logical<4>
+// CHECK-NEXT: [[MARSHAL1:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.logical<4>>) -> memref<i32>
+// CHECK-NEXT: [[INT:%[0-9]+]] = fir.convert [[CONVERT]] : (!fir.logical<4>) -> i32
+// CHECK-NEXT: memref.store [[INT]], [[MARSHAL1]][] : memref<i32>
+func.func @store_scalar(%arg0: !fir.ref<!fir.logical<4>>) {
+ %true = arith.constant true
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "b"} : (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>>
+ %2 = fir.convert %true : (i1) -> !fir.logical<4>
+ fir.store %2 to %1 : !fir.ref<!fir.logical<4>>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir b/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir
new file mode 100644
index 0000000000000..940e0783fb17a
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir
@@ -0,0 +1,206 @@
+/// Verify that fir.convert are only generated one per fir.declare and that
+/// optional marshaling is optimized appropriately.
+///
+/// RUN: fir-opt --enable-fir-convert-opts %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @load_scalar
+// CHECK-COUNT-1: fir.convert
+// CHECK-NOT: fir.convert
+func.func @load_scalar(%arg0: !fir.ref<f32>) {
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "a"} :
+ (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ %2 = fir.load %1 : !fir.ref<f32>
+ %3 = fir.load %1 : !fir.ref<f32>
+ return
+}
+
+// CHECK-LABEL: func.func @load_array1d
+// CHECK-COUNT-1: fir.convert
+// CHECK-NOT: fir.convert
+func.func @load_array1d(%arg0: !fir.ref<!fir.array<3xf32>>) {
+ %c1 = arith.constant 1 : index
+ %c3 = arith.constant 3 : index
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c3 : (index) -> !fir.shape<1>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} :
+ (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) ->
+ !fir.ref<!fir.array<3xf32>>
+ %2 = fir.array_coor %1(%shape) %c1 :
+ (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+ %3 = fir.load %2 : !fir.ref<f32>
+ %4 = fir.array_coor %1(%shape) %c1 :
+ (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+ %5 = fir.load %4 : !fir.ref<f32>
+ return
+}
+
+// CHECK-LABEL: func.func @store_scalar
+// CHECK-COUNT-1: fir.convert
+// CHECK-NOT: fir.convert
+func.func @store_scalar(%arg0: !fir.ref<i32>) {
+ %c7_i32 = arith.constant 7 : i32
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "a"} :
+ (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ fir.store %c7_i32 to %1 : !fir.ref<i32>
+ %2 = fir.load %1 : !fir.ref<i32>
+ return
+}
+
+// CHECK-LABEL: func.func @store_array1d
+// CHECK-COUNT-1: fir.convert
+// CHECK-NOT: fir.convert
+func.func @store_array1d(%arg0: !fir.ref<!fir.array<3xi32>>) {
+ %c1 = arith.constant 1 : index
+ %c7_i32 = arith.constant 7 : i32
+ %c3 = arith.constant 3 : index
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c3 : (index) -> !fir.shape<1>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} :
+ (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) ->
+ !fir.ref<!fir.array<3xi32>>
+ %2 = fir.array_coor %1(%shape) %c1 :
+ (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c7_i32 to %2 : !fir.ref<i32>
+ %3 = fir.array_coor %1(%shape) %c1 :
+ (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ %4 = fir.load %3 : !fir.ref<i32>
+ return
+}
+
+// When Present() checks the same optional memref than the one accessed inside
+// the if statement, marshal is hoisted near the if statement.
+// CHECK-LABEL: func.func @optional_optimized
+// CHECK: [[DECLARE0:%[0-9]]] = fir.declare
+// CHECK: [[DECLARE:%[0-9]]] = fir.declare %arg0
+// CHECK: [[PRESENT:%[0-9]]] = fir.is_present [[DECLARE]]
+// CHECK-NEXT: scf.if [[PRESENT]]
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[DECLARE]]
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x!fir.logical<4>>>) -> memref<?xi32>
+func.func @optional_optimized(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.optional}) {
+ %c1 = arith.constant 1 : index
+ %c3 = arith.constant 3 : index
+ %c0 = arith.constant 0 : index
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.alloca i32 {uniq_name = "i"}
+ %2 = fir.declare %1 {uniq_name = "i"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %3 = fir.declare %arg0 dummy_scope %0 {uniq_name = "r"} :
+ (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) ->
+ !fir.box<!fir.array<?x!fir.logical<4>>>
+ %6 = fir.is_present %3 : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> i1
+ scf.if %6 {
+ %7 = arith.index_cast %c1 : index to i32
+ %c1_0 = arith.constant 1 : index
+ %8 = arith.addi %c3, %c1_0 : index
+ %9 = scf.for %arg1 = %c1 to %8 step %c1 iter_args(%arg2 = %7) -> (i32) {
+ fir.store %arg2 to %2 : !fir.ref<i32>
+ %10 = fir.load %2 : !fir.ref<i32>
+ %11 = arith.extsi %10 : i32 to i64
+ %box_addr = fir.box_addr %3 :
+ (!fir.box<!fir.array<?x!fir.logical<4>>>) ->
+ !fir.ref<!fir.array<?x!fir.logical<4>>>
+ %lb, %extent, %stride = fir.box_dims %3, %c0 :
+ (!fir.box<!fir.array<?x!fir.logical<4>>>, index) ->
+ (index, index, index)
+ %shape = fir.shape %extent : (index) -> !fir.shape<1>
+ %12 = fir.array_coor %box_addr(%shape) %11 :
+ (!fir.ref<!fir.array<?x!fir.logical<4>>>, !fir.shape<1>, i64) ->
+ !fir.ref<!fir.logical<4>>
+ %13 = fir.load %12 : !fir.ref<!fir.logical<4>>
+ %15 = arith.addi %arg1, %c1 : index
+ %16 = fir.load %2 : !fir.ref<i32>
+ %17 = arith.addi %16, %7 : i32
+ scf.yield %17 : i32
+ }
+ fir.store %9 to %2 : !fir.ref<i32>
+ } else {
+ }
+ return
+}
+
+// When optional memref access is not control dependent on a check of it, no
+// hoisting is applied and the marshal is placed closer to the load/store
+// (inside the loop).
+// CHECK-LABEL: func.func @optional
+// CHECK: [[DECLARE1:%[0-9]]] = fir.declare %arg1
+// CHECK: [[DECLARE2:%[0-9]]] = fir.declare
+// CHECK: [[DECLARE0:%[0-9]]] = fir.declare %arg0
+// CHECK: [[PRESENT:%[0-9]]] = fir.is_present [[DECLARE1]]
+// CHECK: scf.if [[PRESENT]]
+// CHECK: scf.for
+// CHECK: [[BOXADDR:%.+]] = fir.box_addr [[DECLARE0]]
+// CHECK: [[MARSHAL:%.+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x!fir.logical<4>>>) -> memref<?xi32>
+func.func @optional(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.optional},
+ %arg1: !fir.ref<!fir.logical<4>> {fir.optional}) {
+ %c1 = arith.constant 1 : index
+ %c3 = arith.constant 3 : index
+ %c0 = arith.constant 0 : index
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg1 dummy_scope %0 {uniq_name = "d"} :
+ (!fir.ref<!fir.logical<4>>, !fir.dscope) -> !fir.ref<!fir.logical<4>>
+ %2 = fir.alloca i32 {uniq_name = "i"}
+ %3 = fir.declare %2 {uniq_name = "i"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %4 = fir.declare %arg0 dummy_scope %0 {uniq_name = "r"} :
+ (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.dscope) ->
+ !fir.box<!fir.array<?x!fir.logical<4>>>
+ %7 = fir.is_present %1 : (!fir.ref<!fir.logical<4>>) -> i1
+ scf.if %7 {
+ %8 = arith.index_cast %c1 : index to i32
+ %c1_0 = arith.constant 1 : index
+ %9 = arith.addi %c3, %c1_0 : index
+ %10 = scf.for %arg2 = %c1 to %9 step %c1 iter_args(%arg3 = %8) -> (i32) {
+ fir.store %arg3 to %3 : !fir.ref<i32>
+ %11 = fir.load %3 : !fir.ref<i32>
+ %12 = arith.extsi %11 : i32 to i64
+ %box_addr = fir.box_addr %4 :
+ (!fir.box<!fir.array<?x!fir.logical<4>>>) ->
+ !fir.ref<!fir.array<?x!fir.logical<4>>>
+ %lb, %extent, %stride = fir.box_dims %4, %c0 :
+ (!fir.box<!fir.array<?x!fir.logical<4>>>, index) ->
+ (index, index, index)
+ %shape = fir.shape %extent : (index) -> !fir.shape<1>
+ %13 = fir.array_coor %box_addr(%shape) %12 :
+ (!fir.ref<!fir.array<?x!fir.logical<4>>>, !fir.shape<1>, i64) ->
+ !fir.ref<!fir.logical<4>>
+ %14 = fir.load %13 : !fir.ref<!fir.logical<4>>
+ %16 = arith.addi %arg2, %c1 : index
+ %17 = fir.load %3 : !fir.ref<i32>
+ %18 = arith.addi %17, %8 : i32
+ scf.yield %18 : i32
+ }
+ fir.store %10 to %3 : !fir.ref<i32>
+ } else {
+ }
+ return
+}
+
+// Derived from a real-world example: ensure that we only generate one marshal
+// for an absent optional argument and reuse it for multiple loads.
+// CHECK-LABEL: func.func @optional_declare
+// CHECK: [[ABSENT:%[0-9]+]] = fir.absent !fir.ref<i32>
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[DECLARE0:%[0-9]+]] = fir.declare [[ABSENT]] dummy_scope [[DUMMY]]
+// CHECK: [[PRESENT:%[0-9]+]] = fir.is_present [[DECLARE0]]
+// CHECK: scf.if [[PRESENT]]
+// CHECK: [[MARSHAL0:%.+]] = fir.convert [[DECLARE0]] : (!fir.ref<i32>) -> memref<i32>
+// CHECK: memref.load [[MARSHAL0]][] : memref<i32>
+func.func @optional_declare() {
+ %c1 = arith.constant 1 : index
+ %c0_i32 = arith.constant 0 : i32
+ %5 = fir.absent !fir.ref<i32>
+ %6 = fir.undefined !fir.dscope
+ %7 = fir.declare %5 dummy_scope %6 {uniq_name = "_QFFtestEd"} :
+ (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ %9 = fir.is_present %7 : (!fir.ref<i32>) -> i1
+ scf.if %9 {
+ %10 = fir.load %7 : !fir.ref<i32>
+ %11 = arith.cmpi eq, %10, %c0_i32 : i32
+ scf.if %11 {
+ %15 = fir.load %7 : !fir.ref<i32>
+ }
+ }
+ return
+}
+
+
diff --git a/flang/test/Transforms/FIRToMemRef/no-declare.mlir b/flang/test/Transforms/FIRToMemRef/no-declare.mlir
new file mode 100644
index 0000000000000..0f01f5767c7a6
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/no-declare.mlir
@@ -0,0 +1,51 @@
+/// Verify that marshals are only generated correctly without declare ops
+
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @nodeclare
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[SHAPE:.*]] = fir.shape %[[C1]] : (index) -> !fir.shape<1>
+// CHECK: %[[COOR:.*]] = fir.array_coor %arg0(%[[SHAPE]]) %[[C1]] : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+// CHECK: %[[C0:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> memref<i32>
+// CHECK: %[[C1M:.*]] = fir.convert %[[COOR]] : (!fir.ref<i32>) -> memref<i32>
+// CHECK: %[[L0:.*]] = memref.load %[[C1M]][] : memref<i32>
+// CHECK: %[[CARG1:.*]] = fir.convert %arg1 : (!fir.ref<i32>) -> memref<i32>
+// CHECK: memref.store %[[L0]], %[[CARG1]][] : memref<i32>
+// CHECK: %[[L1:.*]] = memref.load %[[C0]][] : memref<i32>
+// CHECK: %[[CARG2:.*]] = fir.convert %arg2 : (!fir.ref<i32>) -> memref<i32>
+// CHECK: memref.store %[[L1]], %[[CARG2]][] : memref<i32>
+
+func.func @nodeclare(%arg0: !fir.ref<!fir.array<1xi32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "b"}, %arg2: !fir.ref<i32> {fir.bindc_name = "c"}) attributes {fir.internal_name = ""} {
+ %c1 = arith.constant 1 : index
+ %shape = fir.shape %c1 : (index) -> !fir.shape<1>
+ %0 = fir.array_coor %arg0(%shape) %c1 : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ %1 = fir.load %0 : !fir.ref<i32>
+ fir.store %1 to %arg1 : !fir.ref<i32>
+ %2 = fir.load %0 : !fir.ref<i32>
+ fir.store %2 to %arg2 : !fir.ref<i32>
+ return
+}
+
+// CHECK-LABEL: func.func @nodeclare_regions
+// CHECK-COUNT-4: fir.convert %{{.*}} : (!fir.ref<i32>) -> memref<i32>
+// CHECK-COUNT-1: fir.convert %{{.*}} : (i32) -> f32
+
+func.func @nodeclare_regions(%arg0: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "h11"}, %arg1: !fir.ref<!fir.array<6xi32>> {fir.bindc_name = "rslt"}) attributes {fir.internal_name = "_QPsub11"} {
+ %cst = arith.constant 1.100000e+01 : f32
+ %c1 = arith.constant 1 : index
+ %c1_i32 = arith.constant 1 : i32
+ %c0_i32 = arith.constant 0 : i32
+ %c6 = arith.constant 6 : index
+ %shape = fir.shape %c6 : (index) -> !fir.shape<1>
+ %0 = fir.array_coor %arg1(%shape) %c1 : (!fir.ref<!fir.array<6xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c0_i32 to %0 : !fir.ref<i32>
+ %1 = fir.load %0 : !fir.ref<i32>
+ %2 = fir.convert %1 : (i32) -> f32
+ %3 = arith.cmpf une, %2, %cst fastmath<contract> : f32
+ fir.if %3 {
+ %4 = fir.load %0 : !fir.ref<i32>
+ %5 = arith.addi %4, %c1_i32 : i32
+ fir.store %5 to %0 : !fir.ref<i32>
+ }
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/reject-conversions.mlir b/flang/test/Transforms/FIRToMemRef/reject-conversions.mlir
new file mode 100644
index 0000000000000..d215cf17d9b4a
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/reject-conversions.mlir
@@ -0,0 +1,29 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+
+// reject zero shaped arrays, so none should be converted to memref
+// CHECK-LABEL: func.func @reject_zero_array
+// CHECK: fir.do_loop
+// CHECK: fir.do_loop
+// CHECK: fir.array_coor
+// CHECK-NOT: memref.load
+func.func @reject_zero_array() {
+ %c1 = arith.constant 1 : index
+ %c-2 = arith.constant -2 : index
+ %c0 = arith.constant 0 : index
+ %c-5 = arith.constant -5 : index
+ %c-3 = arith.constant -3 : index
+ %c-6 = arith.constant -6 : index
+ %1 = fir.address_of(@_QFEc) : !fir.ref<!fir.array<0x0xi32>>
+ %2 = fir.shape_shift %c-2, %c0, %c-5, %c0 : (index, index, index, index) -> !fir.shapeshift<2>
+ %3 = fir.declare %1(%2) {uniq_name = "c"} : (!fir.ref<!fir.array<0x0xi32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<0x0xi32>>
+ fir.do_loop %arg0 = %c1 to %c0 step %c1 unordered {
+ fir.do_loop %arg1 = %c1 to %c0 step %c1 unordered {
+ %11 = arith.addi %arg1, %c-3 : index
+ %12 = arith.addi %arg0, %c-6 : index
+ %13 = fir.array_coor %3(%2) %11, %12 : (!fir.ref<!fir.array<0x0xi32>>, !fir.shapeshift<2>, index, index) -> !fir.ref<i32>
+ %14 = fir.load %13 : !fir.ref<i32>
+ }
+ }
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/replace.mlir b/flang/test/Transforms/FIRToMemRef/replace.mlir
new file mode 100644
index 0000000000000..57f6efdaac362
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/replace.mlir
@@ -0,0 +1,29 @@
+/// Verify that marshals are only generated one per fir.declare
+
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// Derived from
+// do i = 1, n
+// a(i) = i
+// call y(i)
+// call z(i)
+// enddo
+
+// CHECK-LABEL: func.func @x_
+// CHECK: [[ALLOCA:%.+]] = memref.alloca() {bindc_name = "i"} : memref<i32>
+// CHECK-NEXT: [[CONVERT0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: [[DECLARE:%[0-9]]] = fir.declare [[CONVERT0]]
+// CHECK-NEXT: [[CONVERT1:%[0-9]]] = fir.convert [[DECLARE]] : (!fir.ref<i32>) -> memref<i32>
+// CHECK-NEXT: [[LOAD:%[0-9]]] = memref.load [[CONVERT1]]
+// CHECK-NEXT: [[CONVERT2:%[0-9]]] = fir.convert [[CONVERT1]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: fir.call @y_([[CONVERT2]])
+// CHECK-NEXT: [[CONVERT3:%[0-9]]] = fir.convert [[CONVERT1]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: fir.call @z_([[CONVERT3]])
+func.func @x_() attributes {fir.internal_name = "_QPx"} {
+ %1 = fir.alloca i32 {bindc_name = "i"}
+ %2 = fir.declare %1 {uniq_name = "_QFxEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %3 = fir.load %2 : !fir.ref<i32>
+ fir.call @y_(%2) fastmath<contract> : (!fir.ref<i32>) -> ()
+ fir.call @z_(%2) fastmath<contract> : (!fir.ref<i32>) -> ()
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/slice.mlir b/flang/test/Transforms/FIRToMemRef/slice.mlir
new file mode 100644
index 0000000000000..f36518cc99443
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/slice.mlir
@@ -0,0 +1,372 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// converted based on example:
+// subroutine copy(a,b)
+// integer, parameter :: n = 5, m = 7
+// integer, dimension(n,m) :: a, b, c
+//
+// a(2:4:2,1:7:3) = b(1:5:3,2:7:2)
+// end
+//
+// program main
+// integer, parameter :: n = 5, m = 7
+// integer, dimension(n,m) :: a, b, c
+//
+// do j = 1, m
+// do i = 1, n
+// a(i,j) = 0
+// b(i,j) = i + (j-1) * m
+// enddo
+// enddo
+//
+// call copy(a,b)
+//
+// print *, a
+// end
+
+
+// CHECK-LABEL: func.func @slice_2d
+// CHECK: %[[C2:.*]] = arith.constant 2 : index
+// CHECK: %[[C3:.*]] = arith.constant 3 : index
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[C7:.*]] = arith.constant 7 : index
+// CHECK: %[[C5:.*]] = arith.constant 5 : index
+// CHECK: %[[UNDEF:.*]] = fir.undefined !fir.dscope
+// CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]], %[[C7]] : (index, index) -> !fir.shape<2>
+// CHECK: %[[SLICE:.*]] = fir.slice %[[C1]], %[[C5]], %[[C3]], %[[C2]], %[[C7]], %[[C2]] : (index, index, index, index, index, index) -> !fir.slice<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg1(%[[SHAPE]]) dummy_scope %[[UNDEF]] {uniq_name = "b"} : (!fir.ref<!fir.array<5x7xi32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x7xi32>>
+// CHECK: [[EMBOX:%[0-9]+]] = fir.embox [[DECLARE]](%[[SHAPE]]) [%[[SLICE]]] : (!fir.ref<!fir.array<5x7xi32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box<!fir.array<2x3xi32>>
+// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi %[[C3]], %[[C1_0]] : index
+// CHECK: scf.for %[[ARG2:.*]] = %[[C1]] to [[ADD1]] step %[[C1]] {
+// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi %[[C2]], %[[C1_1]] : index
+// CHECK: scf.for %[[ARG3:.*]] = %[[C1]] to [[ADD2]] step %[[C1]] {
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<2x3xi32>>) -> !fir.ref<!fir.array<2x3xi32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x7xi32>>) -> memref<7x5xi32>
+// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
+// CHECK: %[[C1_3:.*]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[ARG3]], %[[C1_3]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], %[[C3]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi %[[C1]], %[[C1_2]] : index
+// CHECK: [[ADD3:%[0-9]+]] = arith.addi [[MUL1]], [[SUB2]] : index
+// CHECK: %[[C1_4:.*]] = arith.constant 1 : index
+// CHECK: [[SUB3:%[0-9]+]] = arith.subi %[[ARG2]], %[[C1_4]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB3]], %[[C2]] : index
+// CHECK: [[SUB4:%[0-9]+]] = arith.subi %[[C2]], %[[C1_2]] : index
+// CHECK: [[ADD4:%[0-9]+]] = arith.addi [[MUL2]], [[SUB4]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD4]], [[ADD3]]] : memref<7x5xi32>
+func.func @slice_2d(%arg0: !fir.ref<!fir.array<5x7xi32>>, %arg1: !fir.ref<!fir.array<5x7xi32>>) {
+ %c4 = arith.constant 4 : index
+ %c2 = arith.constant 2 : index
+ %c3 = arith.constant 3 : index
+ %c1 = arith.constant 1 : index
+ %c7 = arith.constant 7 : index
+ %c5 = arith.constant 5 : index
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c5, %c7 : (index, index) -> !fir.shape<2>
+ %slice = fir.slice %c1, %c5, %c3, %c2, %c7, %c2 : (index, index, index, index, index, index) -> !fir.slice<2>
+ %2 = fir.declare %arg1(%shape) dummy_scope %0 {uniq_name = "b"} : (!fir.ref<!fir.array<5x7xi32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x7xi32>>
+ %9 = fir.embox %2(%shape)[%slice] : (!fir.ref<!fir.array<5x7xi32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box<!fir.array<2x3xi32>>
+ %c1_0 = arith.constant 1 : index
+ %11 = arith.addi %c3, %c1_0 : index
+ scf.for %arg2 = %c1 to %11 step %c1 {
+ %c1_1 = arith.constant 1 : index
+ %12 = arith.addi %c2, %c1_1 : index
+ scf.for %arg3 = %c1 to %12 step %c1 {
+ %13 = fir.array_coor %9(%shape) %arg3, %arg2 : (!fir.box<!fir.array<2x3xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
+ %14 = fir.load %13 : !fir.ref<i32>
+ }
+ }
+ return
+}
+
+// subroutine copy(a,b)
+// integer, parameter :: n = 5, m = 7
+// integer, dimension(n, m, m) :: a, b, c
+//
+// a(2:4:2,1:7:3, 2:5:2) = b(1:5:3,2:7:2, 3:7:4)
+// end
+//
+// program main
+// integer, parameter :: n = 5, m = 7
+// integer, dimension(n, m, m) :: a, b, c
+//
+// do k = 1, m
+// do j = 1, m
+// do i = 1, n
+// a(i, j, k) = 0
+// b(i, j, k) = i + (j-1) * m + (k-1) * m * n
+// enddo
+// enddo
+// enddo
+//
+// call copy(a,b)
+//
+// print *, a
+// end
+// CHECK-LABEL: func.func @slice_3d
+// CHECK: %[[C4:.*]] = arith.constant 4 : index
+// CHECK: %[[C2:.*]] = arith.constant 2 : index
+// CHECK: %[[C3:.*]] = arith.constant 3 : index
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[C7:.*]] = arith.constant 7 : index
+// CHECK: %[[C5:.*]] = arith.constant 5 : index
+// CHECK: %[[DUMMY_SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape %[[C5]], %[[C7]], %[[C7]] : (index, index, index) -> !fir.shape<3>
+// CHECK: [[DECLARE_A:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope %[[DUMMY_SCOPE]] {uniq_name = "_QFcopyEa"} : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>, !fir.dscope) -> !fir.ref<!fir.array<5x7x7xi32>>
+// CHECK: [[DECLARE_B:%[0-9]+]] = fir.declare %arg1([[SHAPE]]) dummy_scope %[[DUMMY_SCOPE]] {uniq_name = "_QFcopyEb"} : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>, !fir.dscope) -> !fir.ref<!fir.array<5x7x7xi32>>
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "c", uniq_name = "_QFcopyEc"} : memref<7x7x5xi32>
+// CHECK: [[REFC:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<7x7x5xi32>) -> !fir.ref<!fir.array<5x7x7xi32>>
+// CHECK: [[DECLARE_C:%[0-9]+]] = fir.declare [[REFC]]([[SHAPE]]) {uniq_name = "_QFcopyEc"} : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>) -> !fir.ref<!fir.array<5x7x7xi32>>
+// CHECK: [[ADDR:%[0-9]+]] = fir.address_of(@_QFcopyECm) : !fir.ref<i32>
+// CHECK: %[[SLICE:[0-9]+]] = fir.slice %[[C1]], %[[C5]], %[[C3]], %[[C2]], %[[C7]], %[[C2]], %[[C3]], %[[C7]], %[[C4]] : (index, index, index, index, index, index, index, index, index) -> !fir.slice<3>
+// CHECK: [[EMBOX:%[0-9]+]] = fir.embox [[DECLARE_B]]([[SHAPE]]) [%[[SLICE]]] : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>, !fir.slice<3>) -> !fir.box<!fir.array<2x3x2xi32>>
+// CHECK: fir.do_loop %[[ARG2:.*]] = %[[C1]] to %[[C2]] step %[[C1]] unordered {
+// CHECK: fir.do_loop %[[ARG3:.*]] = %[[C1]] to %[[C3]] step %[[C1]] unordered {
+// CHECK: fir.do_loop %[[ARG4:.*]] = %[[C1]] to %[[C2]] step %[[C1]] unordered {
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<2x3x2xi32>>) -> !fir.ref<!fir.array<2x3x2xi32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE_B]] : (!fir.ref<!fir.array<5x7x7xi32>>) -> memref<7x7x5xi32>
+// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[ARG4]], %[[C1_1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], %[[C3]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi %[[C1]], %[[C1_0]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB2]] : index
+// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
+// CHECK: [[SUB3:%[0-9]+]] = arith.subi %[[ARG3]], %[[C1_2]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB3]], %[[C2]] : index
+// CHECK: [[SUB4:%[0-9]+]] = arith.subi %[[C2]], %[[C1_0]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB4]] : index
+// CHECK: %[[C1_3:.*]] = arith.constant 1 : index
+// CHECK: [[SUB5:%[0-9]+]] = arith.subi %[[ARG2]], %[[C1_3]] : index
+// CHECK: [[MUL3:%[0-9]+]] = arith.muli [[SUB5]], %[[C4]] : index
+// CHECK: [[SUB6:%[0-9]+]] = arith.subi %[[C3]], %[[C1_0]] : index
+// CHECK: [[ADD3:%[0-9]+]] = arith.addi [[MUL3]], [[SUB6]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<7x7x5xi32>
+func.func @slice_3d(%arg0: !fir.ref<!fir.array<5x7x7xi32>> {fir.bindc_name = "a", llvm.nocapture}, %arg1: !fir.ref<!fir.array<5x7x7xi32>> {fir.bindc_name = "b", llvm.nocapture}) attributes {fir.internal_name = "_QPcopy"} {
+ %c4 = arith.constant 4 : index
+ %c2 = arith.constant 2 : index
+ %c3 = arith.constant 3 : index
+ %c1 = arith.constant 1 : index
+ %c7 = arith.constant 7 : index
+ %c5 = arith.constant 5 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.shape %c5, %c7, %c7 : (index, index, index) -> !fir.shape<3>
+ %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFcopyEa"} : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>, !fir.dscope) -> !fir.ref<!fir.array<5x7x7xi32>>
+ %3 = fir.declare %arg1(%1) dummy_scope %0 {uniq_name = "_QFcopyEb"} : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>, !fir.dscope) -> !fir.ref<!fir.array<5x7x7xi32>>
+ %4 = fir.alloca !fir.array<5x7x7xi32> {bindc_name = "c", uniq_name = "_QFcopyEc"}
+ %5 = fir.declare %4(%1) {uniq_name = "_QFcopyEc"} : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>) -> !fir.ref<!fir.array<5x7x7xi32>>
+ %6 = fir.address_of(@_QFcopyECm) : !fir.ref<i32>
+ %10 = fir.slice %c1, %c5, %c3, %c2, %c7, %c2, %c3, %c7, %c4 : (index, index, index, index, index, index, index, index, index) -> !fir.slice<3>
+ %11 = fir.embox %3(%1) [%10] : (!fir.ref<!fir.array<5x7x7xi32>>, !fir.shape<3>, !fir.slice<3>) -> !fir.box<!fir.array<2x3x2xi32>>
+ fir.do_loop %arg2 = %c1 to %c2 step %c1 unordered {
+ fir.do_loop %arg3 = %c1 to %c3 step %c1 unordered {
+ fir.do_loop %arg4 = %c1 to %c2 step %c1 unordered {
+ %14 = fir.array_coor %11 %arg4, %arg3, %arg2 : (!fir.box<!fir.array<2x3x2xi32>>, index, index, index) -> !fir.ref<i32>
+ %15 = fir.load %14 : !fir.ref<i32>
+ }
+ }
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @extract_row
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[C2:.*]] = arith.constant 2 : index
+// CHECK: %[[C3:.*]] = arith.constant 3 : index
+// CHECK: %[[DUMMY_SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape %[[C3]], %[[C3]] : (index, index) -> !fir.shape<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope %[[DUMMY_SCOPE]] {uniq_name = "_QFextract_rowEmatrix"} : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<3x3xi32>>
+// CHECK: %[[UNDEF:.*]] = fir.undefined index
+// CHECK: %[[SLICE:[0-9]+]] = fir.slice %[[C2]], %[[UNDEF]], %[[UNDEF]], %[[C1]], %[[C3]], %[[C1]] : (index, index, index, index, index, index) -> !fir.slice<2>
+// CHECK: [[EMBOX:%[0-9]+]] = fir.embox [[DECLARE]]([[SHAPE]]) [%[[SLICE]]] : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box<!fir.array<3xi32>>
+// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi %[[C3]], %[[C1_0]] : index
+// CHECK: scf.for %[[ARG1:.*]] = %[[C1]] to [[ADD1]] step %[[C1]] {
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<3xi32>>) -> !fir.ref<!fir.array<3xi32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3x3xi32>>) -> memref<3x3xi32>
+// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[C2]], %[[C1_1]] : index
+// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi %[[ARG1]], %[[C1_2]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB2]], %[[C1]] : index
+// CHECK: [[SUB3:%[0-9]+]] = arith.subi %[[C1]], %[[C1_1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL1]], [[SUB3]] : index
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD2]], [[SUB1]]] : memref<3x3xi32>
+func.func @extract_row(%arg0: !fir.ref<!fir.array<3x3xi32>>) {
+ %c1 = arith.constant 1 : index
+ %c2 = arith.constant 2 : index
+ %c3 = arith.constant 3 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.shape %c3, %c3 : (index, index) -> !fir.shape<2>
+ %2 = fir.declare %arg0(%1) dummy_scope %0 {uniq_name = "_QFextract_rowEmatrix"} : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<3x3xi32>>
+ %5 = fir.undefined index
+ %6 = fir.slice %c2, %5, %5, %c1, %c3, %c1 : (index, index, index, index, index, index) -> !fir.slice<2>
+ %7 = fir.embox %2(%1) [%6] : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box<!fir.array<3xi32>>
+ %c1_0 = arith.constant 1 : index
+ %8 = arith.addi %c3, %c1_0 : index
+ scf.for %arg2 = %c1 to %8 step %c1 {
+ %9 = fir.array_coor %7 %arg2 : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32>
+ %10 = fir.load %9 : !fir.ref<i32>
+ }
+ return
+}
+
+
+// CHECK-LABEL: func.func @extract_column
+// CHECK: %[[C10:.*]] = arith.constant 10 : index
+// CHECK: %[[C11:.*]] = arith.constant 11 : index
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[CST:.*]] = arith.constant 1.000000e+00 : f32
+// CHECK: %[[C5:.*]] = arith.constant 5 : index
+// CHECK: %[[C100:.*]] = arith.constant 100 : index
+// CHECK: %[[DUMMY_SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[ADDR:.*]] = fir.address_of(@_QFextract_columnECn) : !fir.ref<i32>
+// CHECK: [[DECLARE_N:%[0-9]+]] = fir.declare %[[ADDR]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "n"} : (!fir.ref<i32>) -> !fir.ref<i32>
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape %[[C100]], %[[C5]] : (index, index) -> !fir.shape<2>
+// CHECK: [[DECLARE_TMP:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope %[[DUMMY_SCOPE]] {uniq_name = "tmp"} : (!fir.ref<!fir.array<100x5xf32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<100x5xf32>>
+// CHECK: %[[UNDEF:.*]] = fir.undefined index
+// CHECK: %[[SLICE:[0-9]+]] = fir.slice %[[C1]], %[[C100]], %[[C11]], %[[C1]], %[[UNDEF]], %[[UNDEF]] : (index, index, index, index, index, index) -> !fir.slice<2>
+// CHECK: [[EMBOX:%[0-9]+]] = fir.embox [[DECLARE_TMP]]([[SHAPE]]) [%[[SLICE]]] : (!fir.ref<!fir.array<100x5xf32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box<!fir.array<10xf32>>
+// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi %[[C10]], %[[C1_0]] : index
+// CHECK: scf.for %[[ARG1:.*]] = %[[C1]] to [[ADD1]] step %[[C1]] {
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE_TMP]] : (!fir.ref<!fir.array<100x5xf32>>) -> memref<5x100xf32>
+// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[C1]], %[[C1_1]] : index
+// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi %[[ARG1]], %[[C1_2]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB2]], %[[C11]] : index
+// CHECK: [[SUB3:%[0-9]+]] = arith.subi %[[C1]], %[[C1_1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL1]], [[SUB3]] : index
+// CHECK: memref.store %[[CST]], [[MARSHAL]][[[SUB1]], [[ADD2]]] : memref<5x100xf32>
+func.func @extract_column(%arg0: !fir.ref<!fir.array<100x5xf32>> {fir.bindc_name = "tmp", llvm.nocapture}) attributes {fir.internal_name = "_QPextract_column"} {
+ %c10 = arith.constant 10 : index
+ %c11 = arith.constant 11 : index
+ %c1 = arith.constant 1 : index
+ %cst = arith.constant 1.000000e+00 : f32
+ %c5 = arith.constant 5 : index
+ %c100 = arith.constant 100 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.address_of(@_QFextract_columnECn) : !fir.ref<i32>
+ %2 = fir.declare %1 {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "n"} : (!fir.ref<i32>) -> !fir.ref<i32>
+ %5 = fir.shape %c100, %c5 : (index, index) -> !fir.shape<2>
+ %6 = fir.declare %arg0(%5) dummy_scope %0 {uniq_name = "tmp"} : (!fir.ref<!fir.array<100x5xf32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<100x5xf32>>
+ %8 = fir.undefined index
+ %9 = fir.slice %c1, %c100, %c11, %c1, %8, %8 : (index, index, index, index, index, index) -> !fir.slice<2>
+ %10 = fir.embox %6(%5) [%9] : (!fir.ref<!fir.array<100x5xf32>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box<!fir.array<10xf32>>
+ %c1_2 = arith.constant 1 : index
+ %11 = arith.addi %c10, %c1_2 : index
+ scf.for %arg1 = %c1 to %11 step %c1 {
+ %12 = fir.array_coor %10 %arg1 : (!fir.box<!fir.array<10xf32>>, index) -> !fir.ref<f32>
+ fir.store %cst to %12 : !fir.ref<f32>
+ }
+ return
+}
+
+
+// CHECK-LABEL: func.func @noslice
+// CHECK: %[[C7:.*]] = arith.constant 7 : index
+// CHECK: %[[C_NEG1:.*]] = arith.constant -1 : index
+// CHECK: %[[C0:.*]] = arith.constant 0 : index
+// CHECK: [[ALLOCA:%.*]] = fir.alloca !fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>> {bindc_name = "c", uniq_name = "_QMcodaFtrythisEc"}
+// CHECK: [[DECLARE:%.*]] = fir.declare [[ALLOCA]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcodaFtrythisEc"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>>
+// CHECK: [[LOADBOX:%.*]] = fir.load [[DECLARE]] : !fir.ref<!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>>
+// CHECK: [[BOXADDR:%.*]] = fir.box_addr [[LOADBOX]] : (!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>) -> !fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>
+// CHECK: [[COORD:%.*]] = fir.coordinate_of [[BOXADDR]], samples : (!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>) -> !fir.ref<!fir.array<7xf32>>
+// CHECK: [[EMBOX:%.*]] = fir.embox [[COORD]] : (!fir.ref<!fir.array<7xf32>>) -> !fir.box<!fir.array<7xf32>>
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: fir.do_loop %[[ARG0:.*]] = %[[C1]] to %[[C7]] step %[[C1]] unordered {
+// CHECK: [[ADD1:%.*]] = arith.addi %[[ARG0]], %[[C_NEG1]] : index
+// CHECK: [[SHIFT:%.*]] = fir.shift %[[C0]] : (index) -> !fir.shift<1>
+// CHECK: [[BOXADDR2:%.*]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<7xf32>>) -> !fir.ref<!fir.array<7xf32>>
+// CHECK: [[MARSHAL:%.*]] = fir.convert [[BOXADDR2]] : (!fir.ref<!fir.array<7xf32>>) -> memref<7xf32>
+// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+// CHECK: [[ADD2:%.*]] = arith.addi %[[ARG0]], %[[C_NEG1]] : index
+// CHECK: [[SUB1:%.*]] = arith.subi [[ADD2]], %[[C0]] : index
+// CHECK: [[MUL1:%.*]] = arith.muli [[SUB1]], %[[C1_0]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi %[[C0]], %[[C0]] : index
+// CHECK: [[ADD3:%.*]] = arith.addi [[MUL1]], [[SUB2]] : index
+// CHECK: [[LOADVAL:%.*]] = memref.load [[MARSHAL]][[[ADD3]]] : memref<7xf32>
+func.func @noslice() {
+ %c7 = arith.constant 7 : index
+ %c-1 = arith.constant -1 : index
+ %c0 = arith.constant 0 : index
+ %7 = fir.alloca !fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>> {bindc_name = "c", uniq_name = "_QMcodaFtrythisEc"}
+ %10 = fir.declare %7 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcodaFtrythisEc"} : (!fir.ref<!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>>
+ %27 = fir.load %10 : !fir.ref<!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>>
+ %28 = fir.box_addr %27 : (!fir.box<!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>>) -> !fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>
+ %31 = fir.coordinate_of %28, samples : (!fir.heap<!fir.type<_QMcodaTcodaK6{samples:!fir.array<7xf32>}>>) -> !fir.ref<!fir.array<7xf32>>
+ %33 = fir.embox %31 : (!fir.ref<!fir.array<7xf32>>) -> !fir.box<!fir.array<7xf32>>
+ %c1_0 = arith.constant 1 : index
+ fir.do_loop %arg0 = %c1_0 to %c7 step %c1_0 unordered {
+ %56 = arith.addi %arg0, %c-1 : index
+ %57 = fir.shift %c0 : (index) -> !fir.shift<1>
+ %58 = fir.array_coor %33(%57) %56 : (!fir.box<!fir.array<7xf32>>, !fir.shift<1>, index) -> !fir.ref<f32>
+ %60 = fir.load %58 : !fir.ref<f32>
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @array_coor_slice() attributes {fir.bindc_name = "tf4a", noinline}
+// CHECK: %[[C0:.*]] = arith.constant 0 : index
+// CHECK: %[[C_NEG1:.*]] = arith.constant -1 : index
+// CHECK: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[C_NEG6:.*]] = arith.constant -6 : index
+// CHECK: %[[C5:.*]] = arith.constant 5 : index
+// CHECK: %[[ALLOCA:.*]] = memref.alloca() : memref<i32>
+// CHECK: %[[MARSHAL1:.*]] = fir.convert %[[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK: %[[DUMMY_SCOPE:[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[ADDR:[0-9]+]] = fir.address_of(@_QFFsECindex) : !fir.ref<!fir.array<5xi32>>
+// CHECK: %[[SHAPE:[0-9]+]] = fir.shape %[[C5]] : (index) -> !fir.shape<1>
+// CHECK: %[[DECLARE:[0-9]+]] = fir.declare %[[ADDR]](%[[SHAPE]]) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QFFsECindex"} : (!fir.ref<!fir.array<5xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>>
+// CHECK: %[[LOAD:[0-9]+]] = memref.load %[[ALLOCA]][] : memref<i32>
+// CHECK: %[[INDEX_CAST:[0-9]+]] = arith.index_cast %[[LOAD]] : i32 to index
+// CHECK: %[[ADD1:[0-9]+]] = arith.addi %[[INDEX_CAST]], %[[C_NEG6]] : index
+// CHECK: %[[DIV:[0-9]+]] = arith.divsi %[[ADD1]], %[[C_NEG1]] : index
+// CHECK: %[[CMP:[0-9]+]] = arith.cmpi sgt, %[[DIV]], %[[C0]] : index
+// CHECK: %[[SELECT:[0-9]+]] = arith.select %[[CMP]], %[[DIV]], %[[C0]] : index
+// CHECK: %[[SHAPE2:[0-9]+]] = fir.shape %[[SELECT]] : (index) -> !fir.shape<1>
+// CHECK: %[[SLICE:[0-9]+]] = fir.slice %[[C5]], %[[INDEX_CAST]], %[[C_NEG1]] : (index, index, index) -> !fir.slice<1>
+// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
+// CHECK: %[[ADD2:[0-9]+]] = arith.addi %[[SELECT]], %[[C1_0]] : index
+// CHECK: scf.for %[[ARG0:.*]] = %[[C1]] to %[[ADD2]] step %[[C1]] {
+// CHECK: %[[MARSHAL2:.*]] = fir.convert %[[DECLARE]] : (!fir.ref<!fir.array<5xi32>>) -> memref<5xi32>
+// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
+// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
+// CHECK: %[[SUB1:[0-9]+]] = arith.subi %[[ARG0]], %[[C1_2]] : index
+// CHECK: %[[MUL1:[0-9]+]] = arith.muli %[[SUB1]], %[[C_NEG1]] : index
+// CHECK: %[[SUB2:[0-9]+]] = arith.subi %[[C5]], %[[C1_1]] : index
+// CHECK: %[[ADD3:[0-9]+]] = arith.addi %[[MUL1]], %[[SUB2]] : index
+// CHECK: %[[LOAD2:[0-9]+]] = memref.load %[[MARSHAL2]][%[[ADD3]]] : memref<5xi32>
+func.func @array_coor_slice() attributes {fir.bindc_name = "tf4a", noinline} {
+ %c0 = arith.constant 0 : index
+ %c-1 = arith.constant -1 : index
+ %c1 = arith.constant 1 : index
+ %c-6 = arith.constant -6 : index
+ %c5 = arith.constant 5 : index
+ %3 = fir.alloca i32 {adapt.valuebyref}
+ %7 = fir.dummy_scope : !fir.dscope
+ %10 = fir.address_of(@_QFFsECindex) : !fir.ref<!fir.array<5xi32>>
+ %11 = fir.shape %c5 : (index) -> !fir.shape<1>
+ %12 = fir.declare %10(%11) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QFFsECindex"} : (!fir.ref<!fir.array<5xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>>
+ %13 = fir.declare %3 dummy_scope %7 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFFsElower"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ %29 = fir.load %13 : !fir.ref<i32>
+ %30 = arith.index_cast %29 : i32 to index
+ %31 = arith.addi %30, %c-6 : index
+ %32 = arith.divsi %31, %c-1 : index
+ %33 = arith.cmpi sgt, %32, %c0 : index
+ %34 = arith.select %33, %32, %c0 : index
+ %35 = fir.shape %34 : (index) -> !fir.shape<1>
+ %36 = fir.slice %c5, %30, %c-1 : (index, index, index) -> !fir.slice<1>
+ %c1_0 = arith.constant 1 : index
+ %40 = arith.addi %34, %c1_0 : index
+ scf.for %arg0 = %c1 to %40 step %c1 {
+ %61 = fir.array_coor %12(%11) [%36] %arg0 : (!fir.ref<!fir.array<5xi32>>, !fir.shape<1>, !fir.slice<1>, index) -> !fir.ref<i32>
+ %62 = fir.load %61 : !fir.ref<i32>
+ }
+ return
+}
+
diff --git a/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir b/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir
new file mode 100644
index 0000000000000..38e4802ea6ab6
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir
@@ -0,0 +1,129 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// subroutine store_dynamic_1d(x)
+// real, dimension(:) :: x
+// x(2) = 3
+// end subroutine store_dynamic_1d
+// CHECK-LABEL: func.func @store_dynamic_1d
+// CHECK: [[CONST2:%.+]] = arith.constant 2 : index
+// CHECK: [[CST:%.+]] = arith.constant 3.000000e+00 : f32
+// CHECK: [[DUMMY:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[ELSIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> index
+// CHECK: [[CONST0:%.+]] = arith.constant 0 : index
+// CHECK: [[DIMS:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV:%[0-9]+]] = arith.divsi [[DIMS]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0_0:%.+]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_0]]], sizes: [[[DIMS]]#1], strides: [[[DIV]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
+// CHECK: memref.store [[CST]], [[REINTERPRET]][[[ADD1]]] : memref<?xf32, strided<[?], offset: ?>>
+func.func @store_dynamic_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+ %c2 = arith.constant 2 : index
+ %cst = arith.constant 3.000000e+00 : f32
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+ %2 = fir.rebox %1 : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+ %3 = fir.array_coor %2 %c2 : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+ fir.store %cst to %3 : !fir.ref<f32>
+ return
+}
+
+// subroutine store_dynamic_2d(x)
+// real, dimension(:, :) :: x
+// x(2, 2) = 3
+// end subroutine store_dynamic_2d
+// CHECK-LABEL: func.func @store_dynamic_2d
+// CHECK: [[CONST2:%.+]] = arith.constant 2 : index
+// CHECK: [[CST:%.+]] = arith.constant 3.000000e+00 : f32
+// CHECK: [[DUMMY:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[CONST1]] : index
+// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
+// CHECK: [[ELSIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> index
+// CHECK: [[CONST1_1:%.+]] = arith.constant 1 : index
+// CHECK: [[DIMS1:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST1_1]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV1:%[0-9]+]] = arith.divsi [[DIMS1]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0:%.+]] = arith.constant 0 : index
+// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0_2:%.+]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_2]]], sizes: [[[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV1]], [[DIV0]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: memref.store [[CST]], [[REINTERPRET]][[[ADD2]], [[ADD1]]] : memref<?x?xf32, strided<[?, ?], offset: ?>>
+func.func @store_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) {
+ %c2 = arith.constant 2 : index
+ %cst = arith.constant 3.000000e+00 : f32
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
+ %2 = fir.rebox %1 : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+ %3 = fir.array_coor %2 %c2, %c2 : (!fir.box<!fir.array<?x?xf32>>, index, index) -> !fir.ref<f32>
+ fir.store %cst to %3 : !fir.ref<f32>
+ return
+}
+
+// subroutine store_dynamic_3d(x)
+// real, dimension(:, :, :) :: x
+// x(2, 2, 3) = 3
+// end subroutine store_dynamic_3d
+// CHECK-LABEL: func.func @store_dynamic_3d
+// CHECK: [[CONST3:%.+]] = arith.constant 3 : index
+// CHECK: [[CONST2:%.+]] = arith.constant 2 : index
+// CHECK: [[CST:%.+]] = arith.constant 3.000000e+00 : f32
+// CHECK: [[DUMMY:%[0-9]+]] = fir.dummy_scope : !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
+// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.box<!fir.array<?x?x?xf32>>
+// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
+// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[CONST1]] : index
+// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
+// CHECK: [[SUB3:%[0-9]+]] = arith.subi [[CONST3]], [[CONST1]] : index
+// CHECK: [[MUL3:%[0-9]+]] = arith.muli [[SUB3]], [[CONST1]] : index
+// CHECK: [[SUB3A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD3:%[0-9]+]] = arith.addi [[MUL3]], [[SUB3A]] : index
+// CHECK: [[ELSIZE:%[0-9]+]] = fir.box_elesize [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> index
+// CHECK: [[CONST2_0:%.+]] = arith.constant 2 : index
+// CHECK: [[DIMS2:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST2_0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV2:%[0-9]+]] = arith.divsi [[DIMS2]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST1_1:%.+]] = arith.constant 1 : index
+// CHECK: [[DIMS1:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST1_1]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV1:%[0-9]+]] = arith.divsi [[DIMS1]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0:%.+]] = arith.constant 0 : index
+// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
+// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
+// CHECK: [[CONST0_2:%.+]] = arith.constant 0 : index
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_2]]], sizes: [[[DIMS2]]#1, [[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV2]], [[DIV1]], [[DIV0]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+// CHECK: memref.store [[CST]], [[REINTERPRET]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+func.func @store_dynamic_3d(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "x"}) {
+ %c3 = arith.constant 3 : index
+ %c2 = arith.constant 2 : index
+ %cst = arith.constant 3.000000e+00 : f32
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
+ %2 = fir.rebox %1 : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.box<!fir.array<?x?x?xf32>>
+ %3 = fir.array_coor %2 %c2, %c2, %c3 : (!fir.box<!fir.array<?x?x?xf32>>, index, index, index) -> !fir.ref<f32>
+ fir.store %cst to %3 : !fir.ref<f32>
+ return
+}
\ No newline at end of file
diff --git a/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir b/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir
new file mode 100644
index 0000000000000..9974c5ab4fbad
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir
@@ -0,0 +1,118 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// subroutine store_shift_1d()
+// real, dimension(2:10) :: x
+// x(9) = 2
+// end subroutine store_shift_1d
+// CHECK-LABEL: func.func @store_shift_1d
+// CHECK: [[CST:%.*]] = arith.constant 2.000000e+00 : f32
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "x"} : memref<9xf32>
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<9xf32>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]] : (index, index) -> !fir.shapeshift<1>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9xf32>>) -> memref<9xf32>
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: memref.store [[CST]], [[MARSHAL2]][[[ADDI1]]] : memref<9xf32>
+func.func @store_shift_1d() {
+ %cst = arith.constant 2.000000e+00 : f32
+ %c2 = arith.constant 2 : index
+ %c9 = arith.constant 9 : index
+ %0 = fir.alloca !fir.array<9xf32> {bindc_name = "x", uniq_name = "x"}
+ %1 = fir.shape_shift %c2, %c9 : (index, index) -> !fir.shapeshift<1>
+ %2 = fir.declare %0(%1) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
+ %3 = fir.array_coor %2(%1) %c9 : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+ fir.store %cst to %3 : !fir.ref<f32>
+ return
+}
+
+// subroutine store_shift_2d()
+// real, dimension(2:10,1:10) :: x
+// x(9,1) = 2
+// end subroutine store_shift_2d
+// CHECK-LABEL: func.func @store_shift_2d
+// CHECK: [[CST:%.*]] = arith.constant 2.000000e+00 : f32
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[C10:%.*]] = arith.constant 10 : index
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "_QFstore_shift_2dEx"} : memref<10x9xf32>
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<10x9xf32>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]] : (index, index, index, index) -> !fir.shapeshift<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFstore_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10xf32>>) -> memref<10x9xf32>
+// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[SUBI3:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1_0]] : index
+// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
+// CHECK: memref.store [[CST]], [[MARSHAL2]][[[ADDI2]], [[ADDI1]]] : memref<10x9xf32>
+func.func @store_shift_2d() {
+ %cst = arith.constant 2.000000e+00 : f32
+ %c2 = arith.constant 2 : index
+ %c9 = arith.constant 9 : index
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ %0 = fir.alloca !fir.array<9x10xf32> {bindc_name = "x", uniq_name = "_QFstore_shift_2dEx"}
+ %1 = fir.shape_shift %c2, %c9, %c1, %c10 : (index, index, index, index) -> !fir.shapeshift<2>
+ %2 = fir.declare %0(%1) {uniq_name = "_QFstore_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
+ %3 = fir.array_coor %2(%1) %c9, %c1 : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>, index, index) -> !fir.ref<f32>
+ fir.store %cst to %3 : !fir.ref<f32>
+ return
+}
+
+// subroutine store_shift_3d()
+// real, dimension(2:10,1:10,3:8) :: x
+// x(9,1,9) = 2
+// end subroutine store_shift_3d
+// CHECK-LABEL: func.func @store_shift_3d
+// CHECK: [[CST:%.*]] = arith.constant 2.000000e+00 : f32
+// CHECK: [[C2:%.*]] = arith.constant 2 : index
+// CHECK: [[C9:%.*]] = arith.constant 9 : index
+// CHECK: [[C1:%.*]] = arith.constant 1 : index
+// CHECK: [[C10:%.*]] = arith.constant 10 : index
+// CHECK: [[C3:%.*]] = arith.constant 3 : index
+// CHECK: [[C8:%.*]] = arith.constant 8 : index
+// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "x"} : memref<8x10x9xf32>
+// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<8x10x9xf32>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]], [[C3]], [[C8]] : (index, index, index, index, index, index) -> !fir.shapeshift<3>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFstore_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10x8xf32>>) -> memref<8x10x9xf32>
+// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
+// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
+// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
+// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
+// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
+// CHECK: [[SUBI3:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1_0]] : index
+// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
+// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
+// CHECK: [[SUBI5:%[0-9]+]] = arith.subi [[C9]], [[C3]] : index
+// CHECK: [[MULI3:%[0-9]+]] = arith.muli [[SUBI5]], [[C1_0]] : index
+// CHECK: [[SUBI6:%[0-9]+]] = arith.subi [[C3]], [[C3]] : index
+// CHECK: [[ADDI3:%[0-9]+]] = arith.addi [[MULI3]], [[SUBI6]] : index
+// CHECK: memref.store [[CST]], [[MARSHAL2]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<8x10x9xf32>
+func.func @store_shift_3d() {
+ %cst = arith.constant 2.000000e+00 : f32
+ %c2 = arith.constant 2 : index
+ %c9 = arith.constant 9 : index
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ %c3 = arith.constant 3 : index
+ %c8 = arith.constant 8 : index
+ %0 = fir.alloca !fir.array<9x10x8xf32> {bindc_name = "x", uniq_name = "x"}
+ %1 = fir.shape_shift %c2, %c9, %c1, %c10, %c3, %c8 : (index, index, index, index, index, index) -> !fir.shapeshift<3>
+ %2 = fir.declare %0(%1) {uniq_name = "_QFstore_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
+ %3 = fir.array_coor %2(%1) %c9, %c1, %c9 : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>, index, index, index) -> !fir.ref<f32>
+ fir.store %cst to %3 : !fir.ref<f32>
+ return
+}
\ No newline at end of file
diff --git a/flang/test/Transforms/FIRToMemRef/store-static-shape.mlir b/flang/test/Transforms/FIRToMemRef/store-static-shape.mlir
new file mode 100644
index 0000000000000..57bca5a095437
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/store-static-shape.mlir
@@ -0,0 +1,75 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+
+// CHECK-LABEL: func.func @store_scalar
+// CHECK: [[CONST7:%.+]] = arith.constant 7 : i32
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<i32>) -> memref<i32>
+// CHECK: memref.store [[CONST7]], [[CONVERT]][] : memref<i32>
+func.func @store_scalar(%arg0: !fir.ref<i32>) {
+ %c7 = arith.constant 7 : i32
+ %0 = fir.undefined !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "a"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+ fir.store %c7 to %1 : !fir.ref<i32>
+ return
+}
+
+
+// CHECK-LABEL: func.func @store_array1d_const
+// CHECK: [[CONST1A:%.+]] = arith.constant 1 : index
+// CHECK: [[CONST3:%.+]] = arith.constant 3 : index
+// CHECK: [[CONST7:%.+]] = arith.constant 7 : i32
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape [[CONST3]] : (index) -> !fir.shape<1>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<3xi32>>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3xi32>>) -> memref<3xi32>
+// CHECK: [[CONST1B:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB:%.+]] = arith.subi [[CONST1A]], [[CONST1B]] : index
+// CHECK: [[MUL:%.+]] = arith.muli [[SUB]], [[CONST1B]] : index
+// CHECK: [[SUBA:%.+]] = arith.subi [[CONST1B]], [[CONST1B]] : index
+// CHECK: [[ADD:%.+]] = arith.addi [[MUL]], [[SUBA]] : index
+// CHECK: memref.store [[CONST7]], [[CONVERT]][[[ADD]]] : memref<3xi32>
+func.func @store_array1d_const(%arg0: !fir.ref<!fir.array<3xi32>>) {
+ %c1 = arith.constant 1 : index
+ %c3 = arith.constant 3 : index
+ %c7 = arith.constant 7 : i32
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c3 : (index) -> !fir.shape<1>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<3xi32>>
+ %2 = fir.array_coor %1(%shape) %c1 : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c7 to %2 : !fir.ref<i32>
+ return
+}
+// CHECK-LABEL: func.func @store_array2d_const
+// CHECK: [[CONST2:%.+]] = arith.constant 2 : index
+// CHECK: [[CONST3:%.+]] = arith.constant 3 : index
+// CHECK: [[CONST5:%.+]] = arith.constant 5 : index
+// CHECK: [[CONST6:%.+]] = arith.constant 6 : index
+// CHECK: [[CONST7:%.+]] = arith.constant 7 : i32
+// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
+// CHECK: [[SHAPE:%[0-9]+]] = fir.shape [[CONST5]], [[CONST6]] : (index, index) -> !fir.shape<2>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<!fir.array<5x6xi32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x6xi32>>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x6xi32>>) -> memref<6x5xi32>
+// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
+// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
+// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
+// CHECK: [[SUB1A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD1:%[0-9]+]] = arith.addi [[MUL1]], [[SUB1A]] : index
+// CHECK: [[SUB2:%[0-9]+]] = arith.subi [[CONST3]], [[CONST1]] : index
+// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[CONST1]] : index
+// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[CONST1]], [[CONST1]] : index
+// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
+// CHECK: memref.store [[CONST7]], [[CONVERT]][[[ADD2]], [[ADD1]]] : memref<6x5xi32>
+func.func @store_array2d_const(%arg0: !fir.ref<!fir.array<5x6xi32>>) {
+ %c2 = arith.constant 2 : index
+ %c3 = arith.constant 3 : index
+ %c5 = arith.constant 5 : index
+ %c6 = arith.constant 6 : index
+ %c7 = arith.constant 7 : i32
+ %0 = fir.undefined !fir.dscope
+ %shape = fir.shape %c5, %c6 : (index, index) -> !fir.shape<2>
+ %1 = fir.declare %arg0(%shape) dummy_scope %0 {uniq_name = "a"} : (!fir.ref<!fir.array<5x6xi32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x6xi32>>
+ %2 = fir.array_coor %1(%shape) %c2, %c3 : (!fir.ref<!fir.array<5x6xi32>>, !fir.shape<2>, index, index) -> !fir.ref<i32>
+ fir.store %c7 to %2 : !fir.ref<i32>
+ return
+}
diff --git a/flang/test/Transforms/FIRToMemRef/tbaa-tag.mlir b/flang/test/Transforms/FIRToMemRef/tbaa-tag.mlir
new file mode 100644
index 0000000000000..4e4c6c4ff6bc0
--- /dev/null
+++ b/flang/test/Transforms/FIRToMemRef/tbaa-tag.mlir
@@ -0,0 +1,44 @@
+// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
+// Derived from:
+// program main
+// real :: array(10)
+// array = 1327
+// array = array + scalar
+// end program
+// CHECK: #tbaa_root = #llvm.tbaa_root<id = "Flang function root _QQmain">
+// CHECK-NEXT: #tbaa_type_desc = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root, 0>}>
+// CHECK-NEXT: #tbaa_type_desc1 = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc, 0>}>
+// CHECK-NEXT: #tbaa_type_desc2 = #llvm.tbaa_type_desc<id = "global data", members = {<#tbaa_type_desc1, 0>}>
+// CHECK-NEXT: #tbaa_type_desc3 = #llvm.tbaa_type_desc<id = "global data/_QFEarray", members = {<#tbaa_type_desc2, 0>}>
+// CHECK-NEXT: #tbaa_tag = #llvm.tbaa_tag<base_type = #tbaa_type_desc3, access_type = #tbaa_type_desc3, offset = 0>
+// CHECK-LABEL: func.func @tbaa
+// CHECK: memref.store %cst, %{{[0-9]+}}[%{{[0-9]+}}] {tbaa = [#tbaa_tag]}
+// CHECK: memref.load %{{[0-9]+}}[%{{[0-9]+}}] {tbaa = [#tbaa_tag]}
+// CHECK: memref.store %{{[0-9]+}}, %{{[0-9]+}}[%{{[0-9]+}}] {tbaa = [#tbaa_tag]}
+func.func @tbaa() {
+ %c1 = arith.constant 1 : index
+ %cst = arith.constant 1.327000e+03 : f32
+ %c10 = arith.constant 10 : index
+ %0 = fir.address_of(@_QFEarray) : !fir.ref<!fir.array<10xf32>>
+ %shape = fir.shape %c10 : (index) -> !fir.shape<1>
+ %1 = fir.declare %0(%shape) {uniq_name = "_QFEarray"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ %2 = fir.alloca f32 {bindc_name = "scalar", uniq_name = "_QFEscalar"}
+ %3 = fir.declare %2 {uniq_name = "_QFEscalar"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %c1_0 = arith.constant 1 : index
+ %4 = arith.addi %c10, %c1_0 : index
+ scf.for %arg0 = %c1 to %4 step %c1 {
+ %7 = fir.array_coor %1(%shape) %arg0 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+ fir.store %cst to %7 {tbaa = [#llvm.tbaa_tag<base_type = <id = "global data/_QFEarray", members = {<#llvm.tbaa_type_desc<id = "global data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QQmain">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "global data/_QFEarray", members = {<#llvm.tbaa_type_desc<id = "global data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QQmain">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !fir.ref<f32>
+ }
+ %5 = fir.load %3 : !fir.ref<f32>
+ %c1_1 = arith.constant 1 : index
+ %6 = arith.addi %c10, %c1_1 : index
+ scf.for %arg0 = %c1 to %6 step %c1 {
+ %7 = fir.array_coor %1(%shape) %arg0 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+ %8 = fir.load %7 {tbaa = [#llvm.tbaa_tag<base_type = <id = "global data/_QFEarray", members = {<#llvm.tbaa_type_desc<id = "global data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QQmain">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "global data/_QFEarray", members = {<#llvm.tbaa_type_desc<id = "global data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QQmain">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !fir.ref<f32>
+ %9 = arith.addf %8, %5 fastmath<contract> : f32
+ fir.store %9 to %7 {tbaa = [#llvm.tbaa_tag<base_type = <id = "global data/_QFEarray", members = {<#llvm.tbaa_type_desc<id = "global data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QQmain">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "global data/_QFEarray", members = {<#llvm.tbaa_type_desc<id = "global data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QQmain">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !fir.ref<f32>
+ }
+ return
+}
+
>From ef2ca11a770b375269edb37d63dc05d85f563282 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 24 Dec 2025 12:43:32 -0800
Subject: [PATCH 2/3] change marshal to memref
---
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 2 +-
.../lib/Optimizer/Transforms/FIRToMemRef.cpp | 138 +++++++++---------
.../Transforms/FIRToMemRef/marshal-opt.mlir | 16 +-
.../Transforms/FIRToMemRef/no-declare.mlir | 2 +-
.../test/Transforms/FIRToMemRef/replace.mlir | 2 +-
.../FIRToMemRef/store-dynamic-shape.mlir | 12 +-
.../FIRToMemRef/store-shift-static.mlir | 24 +--
7 files changed, 98 insertions(+), 98 deletions(-)
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index c5aadb4beac55..8d23e8ceb0b39 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -820,7 +820,7 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
// Handle conversions between pointer-like values and memref descriptors.
// These are produced by FIR-to-MemRef lowering and represent descriptor
- // marshaling rather than pure value conversions.
+ // conversion rather than pure value conversions.
if (auto memRefTy = mlir::dyn_cast<mlir::MemRefType>(toFirTy)) {
mlir::Location loc = convert.getLoc();
mlir::Value basePtr = adaptor.getValue();
diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
index c79425c8a21d2..135046862bfcf 100644
--- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -129,12 +129,12 @@ class FIRToMemRef : public fir::impl::FIRToMemRefBase<FIRToMemRef> {
MemRefInfo getMemRefInfo(Value, PatternRewriter &, FIRToMemRefTypeConverter &,
Operation *);
- MemRefInfo marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp,
+ MemRefInfo convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp,
PatternRewriter &, FIRToMemRefTypeConverter &);
void replaceFIRMemrefs(Value, Value, PatternRewriter &) const;
- FailureOr<Value> getFIRMarshal(Operation *memOp, Operation *memref,
+ FailureOr<Value> getFIRConvert(Operation *memOp, Operation *memref,
PatternRewriter &, FIRToMemRefTypeConverter &);
FailureOr<SmallVector<Value>> getMemrefIndices(fir::ArrayCoorOp, Operation *,
@@ -412,7 +412,7 @@ static Value castTypeToIndexType(Value originalValue,
FailureOr<SmallVector<Value>>
FIRToMemRef::getMemrefIndices(fir::ArrayCoorOp arrayCoorOp, Operation *memref,
- PatternRewriter &rewriter, Value marshal,
+ PatternRewriter &rewriter, Value converted,
Value one) const {
IndexType indexTy = rewriter.getIndexType();
SmallVector<Value> indices;
@@ -491,7 +491,7 @@ FIRToMemRef::getMemrefIndices(fir::ArrayCoorOp arrayCoorOp, Operation *memref,
}
MemRefInfo
-FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
+FIRToMemRef::convertArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
PatternRewriter &rewriter,
FIRToMemRefTypeConverter &typeConverter) {
IndexType indexTy = rewriter.getIndexType();
@@ -507,18 +507,18 @@ FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
rewriter.setInsertionPointAfter(arrayCoorOp);
Location loc = arrayCoorOp->getLoc();
Type elemMemrefTy = typeConverter.convertMemrefType(elemRef.getType());
- Value marshal =
+ Value converted =
fir::ConvertOp::create(rewriter, loc, elemMemrefTy, elemRef);
SmallVector<Value> indices;
- return std::pair{marshal, indices};
+ return std::pair{converted, indices};
}
Operation *memref = firMemref.getDefiningOp();
- FailureOr<Value> marshal;
+ FailureOr<Value> converted;
if (enableFIRConvertOptimizations && isMarshalLike(memref) &&
!fir::isa_fir_type(firMemref.getType())) {
- marshal = firMemref;
+ converted = firMemref;
rewriter.setInsertionPoint(arrayCoorOp);
} else {
Operation *arrayCoorOperation = arrayCoorOp.getOperation();
@@ -544,8 +544,8 @@ FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
}
rewriter.setInsertionPoint(arrayCoorOp);
- marshal = getFIRMarshal(memOp, memref, rewriter, typeConverter);
- if (failed(marshal))
+ converted = getFIRConvert(memOp, memref, rewriter, typeConverter);
+ if (failed(converted))
return failure();
rewriter.setInsertionPointAfter(arrayCoorOp);
@@ -554,21 +554,21 @@ FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
Location loc = arrayCoorOp->getLoc();
Value one = arith::ConstantIndexOp::create(rewriter, loc, 1);
FailureOr<SmallVector<Value>> failureOrIndices =
- getMemrefIndices(arrayCoorOp, memref, rewriter, *marshal, one);
+ getMemrefIndices(arrayCoorOp, memref, rewriter, *converted, one);
if (failed(failureOrIndices))
return failure();
SmallVector<Value> indices = *failureOrIndices;
- if (marshal == firMemref)
- return std::pair{*marshal, indices};
+ if (converted == firMemref)
+ return std::pair{*converted, indices};
- Value marshalVal = *marshal;
- MemRefType memRefTy = dyn_cast<MemRefType>(marshalVal.getType());
+ Value convertedVal = *converted;
+ MemRefType memRefTy = dyn_cast<MemRefType>(convertedVal.getType());
bool isRebox = firMemref.getDefiningOp<fir::ReboxOp>() != nullptr;
if (memRefTy.hasStaticShape() && !isRebox)
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
unsigned rank = arrayCoorOp.getIndices().size();
@@ -633,7 +633,7 @@ FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
int64_t dynamicOffset = ShapedType::kDynamic;
SmallVector<int64_t> dynamicStrides(rank, ShapedType::kDynamic);
- auto stridedLayout = StridedLayoutAttr::get(marshalVal.getContext(),
+ auto stridedLayout = StridedLayoutAttr::get(convertedVal.getContext(),
dynamicOffset, dynamicStrides);
SmallVector<int64_t> dynamicShape(rank, ShapedType::kDynamic);
@@ -643,14 +643,14 @@ FIRToMemRef::marshalArrayCoorOp(Operation *memOp, fir::ArrayCoorOp arrayCoorOp,
Value offset = arith::ConstantIndexOp::create(rewriter, loc, 0);
auto reinterpret = memref::ReinterpretCastOp::create(
- rewriter, loc, memRefTy, *marshal, offset, sizes, strides);
+ rewriter, loc, memRefTy, *converted, offset, sizes, strides);
Value result = reinterpret->getResult(0);
return std::pair{result, indices};
}
FailureOr<Value>
-FIRToMemRef::getFIRMarshal(Operation *memOp, Operation *op,
+FIRToMemRef::getFIRConvert(Operation *memOp, Operation *op,
PatternRewriter &rewriter,
FIRToMemRefTypeConverter &typeConverter) {
if (enableFIRConvertOptimizations && !op->hasOneUse() &&
@@ -804,10 +804,10 @@ MemRefInfo FIRToMemRef::getMemRefInfo(Value firMemref,
if (auto inner = llvm::dyn_cast<MemRefType>(mt.getElementType()))
memrefTy = inner;
}
- Value marshal = fir::ConvertOp::create(rewriter, blockArg.getLoc(),
- memrefTy, blockArg);
+ Value converted = fir::ConvertOp::create(rewriter, blockArg.getLoc(),
+ memrefTy, blockArg);
SmallVector<Value> indices;
- return std::pair{marshal, indices};
+ return std::pair{converted, indices};
}
llvm_unreachable(
"FIRToMemRef: expected defining op or block argument for FIR memref");
@@ -815,7 +815,7 @@ MemRefInfo FIRToMemRef::getMemRefInfo(Value firMemref,
if (auto arrayCoorOp = dyn_cast<fir::ArrayCoorOp>(memrefOp)) {
MemRefInfo memrefInfo =
- marshalArrayCoorOp(memOp, arrayCoorOp, rewriter, typeConverter);
+ convertArrayCoorOp(memOp, arrayCoorOp, rewriter, typeConverter);
if (succeeded(memrefInfo)) {
for (auto user : memrefOp->getUsers()) {
if (!isa<fir::LoadOp, fir::StoreOp>(user)) {
@@ -834,17 +834,17 @@ MemRefInfo FIRToMemRef::getMemRefInfo(Value firMemref,
rewriter.setInsertionPoint(memOp);
if (isMarshalLike(memrefOp)) {
- FailureOr<Value> marshal =
- getFIRMarshal(memOp, memrefOp, rewriter, typeConverter);
- if (failed(marshal)) {
+ FailureOr<Value> converted =
+ getFIRConvert(memOp, memrefOp, rewriter, typeConverter);
+ if (failed(converted)) {
LLVM_DEBUG(llvm::dbgs()
- << "FIRToMemRef: expected FIR memref in marshal, bailing "
+ << "FIRToMemRef: expected FIR memref in convert, bailing "
"out:\n";
firMemref.dump());
return failure();
}
SmallVector<Value> indices;
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
}
if (auto declareOp = dyn_cast<fir::DeclareOp>(memrefOp)) {
@@ -867,84 +867,84 @@ MemRefInfo FIRToMemRef::getMemRefInfo(Value firMemref,
}
}
- FailureOr<Value> marshal =
- getFIRMarshal(memOp, declareOp, rewriter, typeConverter);
- if (failed(marshal)) {
+ FailureOr<Value> converted =
+ getFIRConvert(memOp, declareOp, rewriter, typeConverter);
+ if (failed(converted)) {
LLVM_DEBUG(llvm::dbgs()
- << "FIRToMemRef: unable to create marshal for scalar "
+ << "FIRToMemRef: unable to create convert for scalar "
"memref:\n";
firMemref.dump());
return failure();
}
SmallVector<Value> indices;
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
}
if (auto coordinateOp = dyn_cast<fir::CoordinateOp>(memrefOp)) {
- FailureOr<Value> marshal =
- getFIRMarshal(memOp, coordinateOp, rewriter, typeConverter);
- if (failed(marshal)) {
+ FailureOr<Value> converted =
+ getFIRConvert(memOp, coordinateOp, rewriter, typeConverter);
+ if (failed(converted)) {
LLVM_DEBUG(
llvm::dbgs()
- << "FIRToMemRef: unable to create marshal for derived-type "
+ << "FIRToMemRef: unable to create convert for derived-type "
"memref:\n";
firMemref.dump());
return failure();
}
SmallVector<Value> indices;
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
}
if (auto convertOp = dyn_cast<fir::ConvertOp>(memrefOp)) {
Type fromTy = convertOp->getOperand(0).getType();
Type toTy = firMemref.getType();
if (isa<fir::ReferenceType>(fromTy) && isa<fir::ReferenceType>(toTy)) {
- FailureOr<Value> marshal =
- getFIRMarshal(memOp, convertOp, rewriter, typeConverter);
- if (failed(marshal)) {
+ FailureOr<Value> converted =
+ getFIRConvert(memOp, convertOp, rewriter, typeConverter);
+ if (failed(converted)) {
LLVM_DEBUG(
llvm::dbgs()
- << "FIRToMemRef: unable to create marshal for conversion "
+ << "FIRToMemRef: unable to create convert for conversion "
"op:\n";
firMemref.dump());
return failure();
}
SmallVector<Value> indices;
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
}
}
if (auto boxAddrOp = dyn_cast<fir::BoxAddrOp>(memrefOp)) {
- FailureOr<Value> marshal =
- getFIRMarshal(memOp, boxAddrOp, rewriter, typeConverter);
- if (failed(marshal)) {
+ FailureOr<Value> converted =
+ getFIRConvert(memOp, boxAddrOp, rewriter, typeConverter);
+ if (failed(converted)) {
LLVM_DEBUG(llvm::dbgs()
- << "FIRToMemRef: unable to create marshal for box_addr "
+ << "FIRToMemRef: unable to create convert for box_addr "
"op:\n";
firMemref.dump());
return failure();
}
SmallVector<Value> indices;
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
}
if (memrefIsDeviceData(memrefOp)) {
- FailureOr<Value> marshal =
- getFIRMarshal(memOp, memrefOp, rewriter, typeConverter);
- if (failed(marshal))
+ FailureOr<Value> converted =
+ getFIRConvert(memOp, memrefOp, rewriter, typeConverter);
+ if (failed(converted))
return failure();
SmallVector<Value> indices;
- return std::pair{*marshal, indices};
+ return std::pair{*converted, indices};
}
LLVM_DEBUG(llvm::dbgs()
- << "FIRToMemRef: unable to create marshal for memref value:\n";
+ << "FIRToMemRef: unable to create convert for memref value:\n";
firMemref.dump());
return failure();
}
-void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value marshal,
+void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value converted,
PatternRewriter &rewriter) const {
Operation *op = firMemref.getDefiningOp();
if (op && (isa<fir::ArrayCoorOp>(op) || isMarshalLike(op)))
@@ -954,7 +954,7 @@ void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value marshal,
for (auto user : firMemref.getUsers()) {
if (isMarshalLike(user) || isa<fir::LoadOp, fir::StoreOp>(user))
continue;
- if (!domInfo->dominates(marshal, user))
+ if (!domInfo->dominates(converted, user))
continue;
if (!(isa<omp::AtomicCaptureOp>(user->getParentOp()) ||
@@ -968,7 +968,7 @@ void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value marshal,
for (auto op : worklist) {
rewriter.setInsertionPoint(op);
Location loc = op->getLoc();
- Value replaceConvert = fir::ConvertOp::create(rewriter, loc, ty, marshal);
+ Value replaceConvert = fir::ConvertOp::create(rewriter, loc, ty, converted);
op->replaceUsesOfWith(firMemref, replaceConvert);
}
@@ -979,7 +979,7 @@ void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value marshal,
continue;
if (isa<omp::AtomicCaptureOp>(user->getParentOp()) ||
isa<acc::AtomicCaptureOp>(user->getParentOp())) {
- if (domInfo->dominates(marshal, user))
+ if (domInfo->dominates(converted, user))
worklist.insert(user);
}
}
@@ -998,7 +998,7 @@ void FIRToMemRef::replaceFIRMemrefs(Value firMemref, Value marshal,
if (!replaceConvert) {
rewriter.setInsertionPoint(parentOp);
replaceConvert =
- fir::ConvertOp::create(rewriter, op->getLoc(), ty, marshal);
+ fir::ConvertOp::create(rewriter, op->getLoc(), ty, converted);
}
op->replaceUsesOfWith(firMemref, replaceConvert);
erase.push_back(op);
@@ -1024,17 +1024,17 @@ void FIRToMemRef::rewriteLoadOp(fir::LoadOp load, PatternRewriter &rewriter,
return;
auto originalType = load.getResult().getType();
- auto [marshal, indices] = *memrefInfo;
+ auto [converted, indices] = *memrefInfo;
LLVM_DEBUG(llvm::dbgs()
- << "FIRToMemRef: marshal for FIR load created successfully:\n";
- marshal.dump());
+ << "FIRToMemRef: convert for FIR load created successfully:\n";
+ converted.dump());
rewriter.setInsertionPointAfter(load);
auto attr = (load.getOperation())->getAttr("tbaa");
auto loadOp =
- rewriter.replaceOpWithNewOp<memref::LoadOp>(load, marshal, indices);
+ rewriter.replaceOpWithNewOp<memref::LoadOp>(load, converted, indices);
if (attr)
loadOp.getOperation()->setAttr("tbaa", attr);
@@ -1056,7 +1056,7 @@ void FIRToMemRef::rewriteLoadOp(fir::LoadOp load, PatternRewriter &rewriter,
}
if (!isa<fir::LogicalType>(originalType))
- replaceFIRMemrefs(firMemref, marshal, rewriter);
+ replaceFIRMemrefs(firMemref, converted, rewriter);
}
void FIRToMemRef::rewriteStoreOp(fir::StoreOp store, PatternRewriter &rewriter,
@@ -1074,11 +1074,11 @@ void FIRToMemRef::rewriteStoreOp(fir::StoreOp store, PatternRewriter &rewriter,
if (failed(memrefInfo))
return;
- auto [marshal, indices] = *memrefInfo;
+ auto [converted, indices] = *memrefInfo;
LLVM_DEBUG(
llvm::dbgs()
- << "FIRToMemRef: marshal for FIR store created successfully:\n";
- marshal.dump());
+ << "FIRToMemRef: convert for FIR store created successfully:\n";
+ converted.dump());
Value value = store.getValue();
rewriter.setInsertionPointAfter(store);
@@ -1090,8 +1090,8 @@ void FIRToMemRef::rewriteStoreOp(fir::StoreOp store, PatternRewriter &rewriter,
}
auto attr = (store.getOperation())->getAttr("tbaa");
- auto storeOp = rewriter.replaceOpWithNewOp<memref::StoreOp>(store, value,
- marshal, indices);
+ auto storeOp = rewriter.replaceOpWithNewOp<memref::StoreOp>(
+ store, value, converted, indices);
if (attr)
storeOp.getOperation()->setAttr("tbaa", attr);
@@ -1103,7 +1103,7 @@ void FIRToMemRef::rewriteStoreOp(fir::StoreOp store, PatternRewriter &rewriter,
isLogicalRef = llvm::isa<fir::LogicalType>(refTy.getEleTy());
}
if (!isLogicalRef)
- replaceFIRMemrefs(firMemref, marshal, rewriter);
+ replaceFIRMemrefs(firMemref, converted, rewriter);
}
void FIRToMemRef::runOnOperation() {
diff --git a/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir b/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir
index 940e0783fb17a..6a358cbf1a141 100644
--- a/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir
+++ b/flang/test/Transforms/FIRToMemRef/marshal-opt.mlir
@@ -1,5 +1,5 @@
/// Verify that fir.convert are only generated one per fir.declare and that
-/// optional marshaling is optimized appropriately.
+/// optional conversions are optimized appropriately.
///
/// RUN: fir-opt --enable-fir-convert-opts %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
@@ -70,14 +70,14 @@ func.func @store_array1d(%arg0: !fir.ref<!fir.array<3xi32>>) {
}
// When Present() checks the same optional memref than the one accessed inside
-// the if statement, marshal is hoisted near the if statement.
+// the if statement, the convert is hoisted near the if statement.
// CHECK-LABEL: func.func @optional_optimized
// CHECK: [[DECLARE0:%[0-9]]] = fir.declare
// CHECK: [[DECLARE:%[0-9]]] = fir.declare %arg0
// CHECK: [[PRESENT:%[0-9]]] = fir.is_present [[DECLARE]]
// CHECK-NEXT: scf.if [[PRESENT]]
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[DECLARE]]
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x!fir.logical<4>>>) -> memref<?xi32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x!fir.logical<4>>>) -> memref<?xi32>
func.func @optional_optimized(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.optional}) {
%c1 = arith.constant 1 : index
%c3 = arith.constant 3 : index
@@ -120,7 +120,7 @@ func.func @optional_optimized(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fi
}
// When optional memref access is not control dependent on a check of it, no
-// hoisting is applied and the marshal is placed closer to the load/store
+// hoisting is applied and the convert is placed closer to the load/store
// (inside the loop).
// CHECK-LABEL: func.func @optional
// CHECK: [[DECLARE1:%[0-9]]] = fir.declare %arg1
@@ -130,7 +130,7 @@ func.func @optional_optimized(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fi
// CHECK: scf.if [[PRESENT]]
// CHECK: scf.for
// CHECK: [[BOXADDR:%.+]] = fir.box_addr [[DECLARE0]]
-// CHECK: [[MARSHAL:%.+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x!fir.logical<4>>>) -> memref<?xi32>
+// CHECK: [[CONVERT:%.+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x!fir.logical<4>>>) -> memref<?xi32>
func.func @optional(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.optional},
%arg1: !fir.ref<!fir.logical<4>> {fir.optional}) {
%c1 = arith.constant 1 : index
@@ -175,7 +175,7 @@ func.func @optional(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.optional
return
}
-// Derived from a real-world example: ensure that we only generate one marshal
+// Derived from a real-world example: ensure that we only generate one convert
// for an absent optional argument and reuse it for multiple loads.
// CHECK-LABEL: func.func @optional_declare
// CHECK: [[ABSENT:%[0-9]+]] = fir.absent !fir.ref<i32>
@@ -183,8 +183,8 @@ func.func @optional(%arg0: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.optional
// CHECK: [[DECLARE0:%[0-9]+]] = fir.declare [[ABSENT]] dummy_scope [[DUMMY]]
// CHECK: [[PRESENT:%[0-9]+]] = fir.is_present [[DECLARE0]]
// CHECK: scf.if [[PRESENT]]
-// CHECK: [[MARSHAL0:%.+]] = fir.convert [[DECLARE0]] : (!fir.ref<i32>) -> memref<i32>
-// CHECK: memref.load [[MARSHAL0]][] : memref<i32>
+// CHECK: [[CONVERT0:%.+]] = fir.convert [[DECLARE0]] : (!fir.ref<i32>) -> memref<i32>
+// CHECK: memref.load [[CONVERT0]][] : memref<i32>
func.func @optional_declare() {
%c1 = arith.constant 1 : index
%c0_i32 = arith.constant 0 : i32
diff --git a/flang/test/Transforms/FIRToMemRef/no-declare.mlir b/flang/test/Transforms/FIRToMemRef/no-declare.mlir
index 0f01f5767c7a6..664da0a0b38a2 100644
--- a/flang/test/Transforms/FIRToMemRef/no-declare.mlir
+++ b/flang/test/Transforms/FIRToMemRef/no-declare.mlir
@@ -1,4 +1,4 @@
-/// Verify that marshals are only generated correctly without declare ops
+/// Verify that converts are only generated correctly without declare ops
// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
diff --git a/flang/test/Transforms/FIRToMemRef/replace.mlir b/flang/test/Transforms/FIRToMemRef/replace.mlir
index 57f6efdaac362..3fa47a40a0671 100644
--- a/flang/test/Transforms/FIRToMemRef/replace.mlir
+++ b/flang/test/Transforms/FIRToMemRef/replace.mlir
@@ -1,4 +1,4 @@
-/// Verify that marshals are only generated one per fir.declare
+/// Verify that converts are only generated one per fir.declare
// RUN: fir-opt %s --fir-to-memref --allow-unregistered-dialect | FileCheck %s
diff --git a/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir b/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir
index 38e4802ea6ab6..564dca0ed28c3 100644
--- a/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir
+++ b/flang/test/Transforms/FIRToMemRef/store-dynamic-shape.mlir
@@ -11,7 +11,7 @@
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
@@ -22,7 +22,7 @@
// CHECK: [[DIMS:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
// CHECK: [[DIV:%[0-9]+]] = arith.divsi [[DIMS]]#2, [[ELSIZE]] : index
// CHECK: [[CONST0_0:%.+]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_0]]], sizes: [[[DIMS]]#1], strides: [[[DIV]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[CONST0_0]]], sizes: [[[DIMS]]#1], strides: [[[DIV]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
// CHECK: memref.store [[CST]], [[REINTERPRET]][[[ADD1]]] : memref<?xf32, strided<[?], offset: ?>>
func.func @store_dynamic_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
%c2 = arith.constant 2 : index
@@ -46,7 +46,7 @@ func.func @store_dynamic_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name =
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
@@ -64,7 +64,7 @@ func.func @store_dynamic_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name =
// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
// CHECK: [[CONST0_2:%.+]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_2]]], sizes: [[[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV1]], [[DIV0]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[CONST0_2]]], sizes: [[[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV1]], [[DIV0]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
// CHECK: memref.store [[CST]], [[REINTERPRET]][[[ADD2]], [[ADD1]]] : memref<?x?xf32, strided<[?, ?], offset: ?>>
func.func @store_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) {
%c2 = arith.constant 2 : index
@@ -89,7 +89,7 @@ func.func @store_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.box<!fir.array<?x?x?xf32>>
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
@@ -114,7 +114,7 @@ func.func @store_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name
// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
// CHECK: [[CONST0_2:%.+]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_2]]], sizes: [[[DIMS2]]#1, [[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV2]], [[DIV1]], [[DIV0]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[CONST0_2]]], sizes: [[[DIMS2]]#1, [[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV2]], [[DIV1]], [[DIV0]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
// CHECK: memref.store [[CST]], [[REINTERPRET]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
func.func @store_dynamic_3d(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "x"}) {
%c3 = arith.constant 3 : index
diff --git a/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir b/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir
index 9974c5ab4fbad..6b1d0134e8fec 100644
--- a/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir
+++ b/flang/test/Transforms/FIRToMemRef/store-shift-static.mlir
@@ -9,16 +9,16 @@
// CHECK: [[C2:%.*]] = arith.constant 2 : index
// CHECK: [[C9:%.*]] = arith.constant 9 : index
// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "x"} : memref<9xf32>
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<9xf32>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<9xf32>) -> !fir.ref<!fir.array<9xf32>>
// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]] : (index, index) -> !fir.shapeshift<1>
-// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9xf32>>) -> memref<9xf32>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[CONVERT1]]([[SHAPE_SHIFT]]) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9xf32>>) -> memref<9xf32>
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
-// CHECK: memref.store [[CST]], [[MARSHAL2]][[[ADDI1]]] : memref<9xf32>
+// CHECK: memref.store [[CST]], [[CONVERT2]][[[ADDI1]]] : memref<9xf32>
func.func @store_shift_1d() {
%cst = arith.constant 2.000000e+00 : f32
%c2 = arith.constant 2 : index
@@ -42,10 +42,10 @@ func.func @store_shift_1d() {
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[C10:%.*]] = arith.constant 10 : index
// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "_QFstore_shift_2dEx"} : memref<10x9xf32>
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<10x9xf32>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<10x9xf32>) -> !fir.ref<!fir.array<9x10xf32>>
// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]] : (index, index, index, index) -> !fir.shapeshift<2>
-// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFstore_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10xf32>>) -> memref<10x9xf32>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[CONVERT1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFstore_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10xf32>>) -> memref<10x9xf32>
// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
@@ -55,7 +55,7 @@ func.func @store_shift_1d() {
// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1_0]] : index
// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
-// CHECK: memref.store [[CST]], [[MARSHAL2]][[[ADDI2]], [[ADDI1]]] : memref<10x9xf32>
+// CHECK: memref.store [[CST]], [[CONVERT2]][[[ADDI2]], [[ADDI1]]] : memref<10x9xf32>
func.func @store_shift_2d() {
%cst = arith.constant 2.000000e+00 : f32
%c2 = arith.constant 2 : index
@@ -83,10 +83,10 @@ func.func @store_shift_2d() {
// CHECK: [[C3:%.*]] = arith.constant 3 : index
// CHECK: [[C8:%.*]] = arith.constant 8 : index
// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "x"} : memref<8x10x9xf32>
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<8x10x9xf32>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<8x10x9xf32>) -> !fir.ref<!fir.array<9x10x8xf32>>
// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]], [[C3]], [[C8]] : (index, index, index, index, index, index) -> !fir.shapeshift<3>
-// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFstore_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10x8xf32>>) -> memref<8x10x9xf32>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[CONVERT1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFstore_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10x8xf32>>) -> memref<8x10x9xf32>
// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
@@ -100,7 +100,7 @@ func.func @store_shift_2d() {
// CHECK: [[MULI3:%[0-9]+]] = arith.muli [[SUBI5]], [[C1_0]] : index
// CHECK: [[SUBI6:%[0-9]+]] = arith.subi [[C3]], [[C3]] : index
// CHECK: [[ADDI3:%[0-9]+]] = arith.addi [[MULI3]], [[SUBI6]] : index
-// CHECK: memref.store [[CST]], [[MARSHAL2]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<8x10x9xf32>
+// CHECK: memref.store [[CST]], [[CONVERT2]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<8x10x9xf32>
func.func @store_shift_3d() {
%cst = arith.constant 2.000000e+00 : f32
%c2 = arith.constant 2 : index
>From f1a3933a7c3f0f69a367a04a7d7430f0db5b7aef Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Wed, 24 Dec 2025 12:52:54 -0800
Subject: [PATCH 3/3] change marshal to memref
---
.../Transforms/FIRToMemRefTypeConverter.h | 2 +-
flang/test/Transforms/FIRToMemRef/alloca.mlir | 10 +++----
.../Transforms/FIRToMemRef/array-coor-op.mlir | 4 +--
.../test/Transforms/FIRToMemRef/complex.mlir | 8 +++---
.../Transforms/FIRToMemRef/derived-types.mlir | 8 +++---
flang/test/Transforms/FIRToMemRef/index.mlir | 8 +++---
.../FIRToMemRef/load-dynamic-shape.mlir | 12 ++++-----
.../FIRToMemRef/load-shift-dynamic.mlir | 12 ++++-----
.../FIRToMemRef/load-shift-static.mlir | 24 ++++++++---------
.../FIRToMemRef/load-static-shape.mlir | 12 ++++-----
.../test/Transforms/FIRToMemRef/logical.mlir | 8 +++---
flang/test/Transforms/FIRToMemRef/slice.mlir | 26 +++++++++----------
12 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
index d0907ecdd6160..b43b0113c6409 100644
--- a/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
+++ b/flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h
@@ -66,7 +66,7 @@ class FIRToMemRefTypeConverter : public mlir::TypeConverter {
void setConvertScalarTypesOnly(bool value) { convertScalarTypesOnly = value; }
/// Return true if the given FIR type can be converted to a MemRef-typed
- /// descriptor (i.e. is a supported base element for MemRef marshaling).
+ /// descriptor (i.e. is a supported base element for MemRef converting).
bool convertibleMemrefType(mlir::Type ty) {
if (auto refTy = mlir::dyn_cast<fir::ReferenceType>(ty)) {
auto elTy = refTy.getElementType();
diff --git a/flang/test/Transforms/FIRToMemRef/alloca.mlir b/flang/test/Transforms/FIRToMemRef/alloca.mlir
index a60ea6354a45d..b2859370903f4 100644
--- a/flang/test/Transforms/FIRToMemRef/alloca.mlir
+++ b/flang/test/Transforms/FIRToMemRef/alloca.mlir
@@ -8,10 +8,10 @@
// CHECK-LABEL: func.func @alloca
// CHECK: [[ALLOCA:%.+]] = memref.alloca() : memref<i32>
-// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: [[CONVERT0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
// CHECK: [[CONSTANT:%.+]] = arith.constant 1 : i32
// CHECK: memref.store [[CONSTANT]], [[ALLOCA]][] : memref<i32>
-// CHECK: fir.call @f([[MARSHAL0]])
+// CHECK: fir.call @f([[CONVERT0]])
func.func @alloca(%arg0: !fir.ref<f32> {fir.bindc_name = "a"}) {
%0 = fir.alloca i32 {adapt.valuebyref}
@@ -32,7 +32,7 @@ func.func private @f(!fir.ref<i32>)
// CHECK-LABEL: func.func @passbyvalue
// CHECK: [[ALLOCA:%.+]] = memref.alloca() : memref<i32>
-// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: [[CONVERT0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
// CHECK-NEXT: memref.store %arg0, [[ALLOCA]][] : memref<i32>
func.func @passbyvalue(%arg0: i32 {fir.bindc_name = "x"}) {
@@ -52,7 +52,7 @@ func.func @passbyvalue(%arg0: i32 {fir.bindc_name = "x"}) {
// CHECK: [[CON5:%.+]] = arith.constant 5
// CHECK-NEXT: [[CON3:%.+]] = arith.constant 3
// CHECK-NEXT: [[ALLOCA:%.+]] = memref.alloca([[CON3]], [[CON5]]) {bindc_name = "a"} : memref<?x?xf32>
-// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<?x?xf32>) -> !fir.ref<!fir.array<?x?xf32>>
+// CHECK-NEXT: [[CONVERT0:%[0-9]]] = fir.convert [[ALLOCA]] : (memref<?x?xf32>) -> !fir.ref<!fir.array<?x?xf32>>
func.func @_QPalloca_2d() {
%0 = arith.constant 5 : index
@@ -64,7 +64,7 @@ func.func @_QPalloca_2d() {
// CHECK-LABEL: func.func @alloca_nonconvertible
// CHECK-NEXT: [[ALLOCA1:%.+]] = fir.alloca
// CHECK-NEXT: [[ALLOCA2:%.+]] = memref.alloca
-// CHECK-NEXT: [[MARSHAL0:%[0-9]]] = fir.convert [[ALLOCA2]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK-NEXT: [[CONVERT0:%[0-9]]] = fir.convert [[ALLOCA2]] : (memref<i32>) -> !fir.ref<i32>
func.func @alloca_nonconvertible() {
%0 = fir.alloca !fir.box<!fir.array<20xi32>>
%1 = fir.alloca i32
diff --git a/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir b/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir
index 4ad3e045ac653..a53bdf3bf5ef1 100644
--- a/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir
+++ b/flang/test/Transforms/FIRToMemRef/array-coor-op.mlir
@@ -24,13 +24,13 @@
// CHECK: [[DECLARE:%.+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]]
// CHECK: [[COOR1:%.+]] = fir.array_coor [[DECLARE]]([[SHAPE]]) [[C1]] : (!fir.ref<!fir.array<8xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
// CHECK: [[SLICE:%.+]] = fir.convert [[COOR1]] : (!fir.ref<i32>) -> !fir.ref<!fir.array<4xi32>>
-// CHECK: [[MARSHAL:%.+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<8xi32>>) -> memref<8xi32>
+// CHECK: [[CONVERT:%.+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<8xi32>>) -> memref<8xi32>
// CHECK: [[C1B:%.+]] = arith.constant 1 : index
// CHECK: [[SUB:%.+]] = arith.subi [[C5]], [[C1B]] : index
// CHECK: [[MUL:%.+]] = arith.muli [[SUB]], [[C1B]] : index
// CHECK: [[SUB2:%.+]] = arith.subi [[C1B]], [[C1B]] : index
// CHECK: [[IDX:%.+]] = arith.addi [[MUL]], [[SUB2]] : index
-// CHECK: memref.store [[C1_I32]], [[MARSHAL]][[[IDX]]] : memref<8xi32>
+// CHECK: memref.store [[C1_I32]], [[CONVERT]][[[IDX]]] : memref<8xi32>
func.func @slice(%arg0: !fir.ref<!fir.array<8xi32>>){
%c5 = arith.constant 5 : index
%c1_i32 = arith.constant 1 : i32
diff --git a/flang/test/Transforms/FIRToMemRef/complex.mlir b/flang/test/Transforms/FIRToMemRef/complex.mlir
index 738d1b7f4ea08..fdf54fe2b0457 100644
--- a/flang/test/Transforms/FIRToMemRef/complex.mlir
+++ b/flang/test/Transforms/FIRToMemRef/complex.mlir
@@ -3,10 +3,10 @@
// CHECK-LABEL: func.func @convert_complex_
// CHECK: [[DECL0:%[0-9]+]] = fir.declare %arg0
// CHECK: [[DECL1:%[0-9]+]] = fir.declare %arg1
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[DECL1]] : (!fir.ref<complex<f32>>) -> memref<complex<f32>>
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL1]][] : memref<complex<f32>>
-// CHECK: [[MARSHAL0:%[0-9]+]] = fir.convert [[DECL0]] : (!fir.ref<complex<f32>>) -> memref<complex<f32>>
-// CHECK: memref.store [[LOAD]], [[MARSHAL0]][] : memref<complex<f32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[DECL1]] : (!fir.ref<complex<f32>>) -> memref<complex<f32>>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT1]][] : memref<complex<f32>>
+// CHECK: [[CONVERT0:%[0-9]+]] = fir.convert [[DECL0]] : (!fir.ref<complex<f32>>) -> memref<complex<f32>>
+// CHECK: memref.store [[LOAD]], [[CONVERT0]][] : memref<complex<f32>>
func.func @convert_complex_(%arg0: !fir.ref<complex<f32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<complex<f32>> {fir.bindc_name = "b"}) attributes {fir.internal_name = "_QPconvert_complex"} {
%0 = fir.dummy_scope : !fir.dscope
diff --git a/flang/test/Transforms/FIRToMemRef/derived-types.mlir b/flang/test/Transforms/FIRToMemRef/derived-types.mlir
index 0bcf926c4bdca..06e2e01789412 100644
--- a/flang/test/Transforms/FIRToMemRef/derived-types.mlir
+++ b/flang/test/Transforms/FIRToMemRef/derived-types.mlir
@@ -3,8 +3,8 @@
// CHECK-LABEL: func.func @load_scalar
// CHECK: [[INDEX:%[0-9]]] = fir.field_index
// CHECK: [[COORD:%[0-9]]] = fir.coordinate_of
-// CHECK-NEXT: [[MARSHAL:%[0-9]]] = fir.convert [[COORD]] : (!fir.ref<f32>) -> memref<f32>
-// CHECK-NEXT: memref.load [[MARSHAL]][] : memref<f32>
+// CHECK-NEXT: [[CONVERT:%[0-9]]] = fir.convert [[COORD]] : (!fir.ref<f32>) -> memref<f32>
+// CHECK-NEXT: memref.load [[CONVERT]][] : memref<f32>
func.func @load_scalar(%arg0: !fir.ref<!fir.type<DerivedType{a:f32}>>) {
%0 = fir.undefined !fir.dscope
%1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "dtype"} : (!fir.ref<!fir.type<DerivedType{a:f32}>>, !fir.dscope) -> !fir.ref<!fir.type<DerivedType{a:f32}>>
@@ -17,8 +17,8 @@ func.func @load_scalar(%arg0: !fir.ref<!fir.type<DerivedType{a:f32}>>) {
// CHECK-LABEL: func.func @store_scalar
// CHECK: [[INDEX:%[0-9]]] = fir.field_index
// CHECK: [[COORD:%[0-9]]] = fir.coordinate_of
-// CHECK-NEXT: [[MARSHAL:%[0-9]]] = fir.convert [[COORD]] : (!fir.ref<f32>) -> memref<f32>
-// CHECK-NEXT: memref.store %4, [[MARSHAL]][] : memref<f32>
+// CHECK-NEXT: [[CONVERT:%[0-9]]] = fir.convert [[COORD]] : (!fir.ref<f32>) -> memref<f32>
+// CHECK-NEXT: memref.store %4, [[CONVERT]][] : memref<f32>
func.func @store_scalar(%arg0: !fir.ref<!fir.type<DerivedType{a:f32}>>, %arg1: !fir.ref<f32>) {
%0 = fir.undefined !fir.dscope
%1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "dtype"} : (!fir.ref<!fir.type<DerivedType{a:f32}>>, !fir.dscope) -> !fir.ref<!fir.type<DerivedType{a:f32}>>
diff --git a/flang/test/Transforms/FIRToMemRef/index.mlir b/flang/test/Transforms/FIRToMemRef/index.mlir
index aa33890d6b70e..58e7ab094f82d 100644
--- a/flang/test/Transforms/FIRToMemRef/index.mlir
+++ b/flang/test/Transforms/FIRToMemRef/index.mlir
@@ -8,16 +8,16 @@
// CHECK: [[SHAPE:%.+]] = fir.shape [[C3]] : (index) -> !fir.shape<1>
// CHECK: [[DECLARE0:%.+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]]
// CHECK: [[DECLARE1:%.+]] = fir.declare %arg1 dummy_scope [[DUMMY]]
-// CHECK: [[MARSHAL1:%.+]] = fir.convert [[DECLARE1]] : (!fir.ref<i64>) -> memref<i64>
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL1]][] : memref<i64>
-// CHECK: [[MARSHAL0:%.+]] = fir.convert [[DECLARE0]] : (!fir.ref<!fir.array<3xf32>>) -> memref<3xf32>
+// CHECK: [[CONVERT1:%.+]] = fir.convert [[DECLARE1]] : (!fir.ref<i64>) -> memref<i64>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT1]][] : memref<i64>
+// CHECK: [[CONVERT0:%.+]] = fir.convert [[DECLARE0]] : (!fir.ref<!fir.array<3xf32>>) -> memref<3xf32>
// CHECK: [[C1:%.+]] = arith.constant 1 : index
// CHECK-NEXT: [[CAST:%[0-9]+]] = arith.index_cast [[LOAD]] : i64 to index
// CHECK-NEXT: [[SUB:%.+]] = arith.subi [[CAST]], [[C1]] : index
// CHECK-NEXT: [[MUL:%.+]] = arith.muli [[SUB]], [[C1]] : index
// CHECK-NEXT: [[SUBA:%.+]] = arith.subi [[C1]], [[C1]] : index
// CHECK-NEXT: [[ADD:%.+]] = arith.addi [[MUL]], [[SUBA]] : index
-// CHECK-NEXT: memref.load [[MARSHAL0]][[[ADD]]] : memref<3xf32>
+// CHECK-NEXT: memref.load [[CONVERT0]][[[ADD]]] : memref<3xf32>
func.func @load_array1d_var(%arg0: !fir.ref<!fir.array<3xf32>>, %arg1: !fir.ref<i64>) {
%c3 = arith.constant 3 : index
%0 = fir.undefined !fir.dscope
diff --git a/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir b/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir
index 0b48898a1bbe6..2107218130a74 100644
--- a/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir
+++ b/flang/test/Transforms/FIRToMemRef/load-dynamic-shape.mlir
@@ -11,7 +11,7 @@
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST9]], [[CONST1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
@@ -22,7 +22,7 @@
// CHECK: [[DIMS:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
// CHECK: [[DIV:%[0-9]+]] = arith.divsi [[DIMS]]#2, [[ELSIZE]] : index
// CHECK: [[CONST0_0:%.+]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_0]]], sizes: [[[DIMS]]#1], strides: [[[DIV]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[CONST0_0]]], sizes: [[[DIMS]]#1], strides: [[[DIV]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET]][[[ADD1]]] : memref<?xf32, strided<[?], offset: ?>>
func.func @load_descriptor(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
%c9 = arith.constant 9 : index
@@ -47,7 +47,7 @@ func.func @load_descriptor(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name =
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "_QFload_static_1dEx"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST9]], [[CONST1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
@@ -65,7 +65,7 @@ func.func @load_descriptor(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name =
// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
// CHECK: [[CONST0_1:%.+]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_1]]], sizes: [[[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV1]], [[DIV0]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[CONST0_1]]], sizes: [[[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV1]], [[DIV0]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET]][[[ADD2]], [[ADD1]]] : memref<?x?xf32, strided<[?, ?], offset: ?>>
func.func @load_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) {
%c3 = arith.constant 3 : index
@@ -91,7 +91,7 @@ func.func @load_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.box<!fir.array<?x?x?xf32>>
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOXADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
// CHECK: [[CONST1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[CONST2]], [[CONST1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[CONST1]] : index
@@ -116,7 +116,7 @@ func.func @load_dynamic_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name
// CHECK: [[DIMS0:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[CONST0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: [[DIV0:%[0-9]+]] = arith.divsi [[DIMS0]]#2, [[ELSIZE]] : index
// CHECK: [[CONST0_2:%.+]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[CONST0_2]]], sizes: [[[DIMS2]]#1, [[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV2]], [[DIV1]], [[DIV0]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+// CHECK: [[REINTERPRET:%.+]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[CONST0_2]]], sizes: [[[DIMS2]]#1, [[DIMS1]]#1, [[DIMS0]]#1], strides: [[[DIV2]], [[DIV1]], [[DIV0]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
func.func @load_dynamic_3d(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "x"}) {
%c3 = arith.constant 3 : index
diff --git a/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir b/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir
index 9a12c1d4fc011..f1eda57f1e416 100644
--- a/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir
+++ b/flang/test/Transforms/FIRToMemRef/load-shift-dynamic.mlir
@@ -19,7 +19,7 @@
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHIFT]]) dummy_scope [[DUMMY_SCOPE]] {uniq_name = "x"} : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]]([[SHIFT]]) : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>) -> !fir.box<!fir.array<?xf32>>
// CHECK: [[BOX_ADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?xf32>>) -> memref<?xf32>
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI:%[0-9]+]] = arith.subi [[C6]], [[C1]] : index
// CHECK: [[MULI:%[0-9]+]] = arith.muli [[SUBI]], [[C1]] : index
@@ -30,7 +30,7 @@
// CHECK: [[BOX_DIMS:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
// CHECK: [[DIVSI:%[0-9]+]] = arith.divsi [[BOX_DIMS]]#2, [[BOX_ELESIZE]] : index
// CHECK: [[C0_0:%.*]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[C0_0]]], sizes: [[[BOX_DIMS]]#1], strides: [[[DIVSI]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
+// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[C0_0]]], sizes: [[[BOX_DIMS]]#1], strides: [[[DIVSI]]] : memref<?xf32> to memref<?xf32, strided<[?], offset: ?>>
// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET_CAST]][[[ADDI]]] : memref<?xf32, strided<[?], offset: ?>>
func.func @load_shift_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
%c6 = arith.constant 6 : index
@@ -65,7 +65,7 @@ func.func @load_shift_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHIFT]]) dummy_scope [[DUMMY_SCOPE]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>, !fir.dscope) -> !fir.box<!fir.array<?x?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]]([[SHIFT]]) : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?xf32>>
// CHECK: [[BOX_ADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.ref<!fir.array<?x?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?x?xf32>>) -> memref<?x?xf32>
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C6]], [[INDEX_CAST1]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
@@ -83,7 +83,7 @@ func.func @load_shift_1d(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x
// CHECK: [[BOX_DIMS2:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C0]] : (!fir.box<!fir.array<?x?xf32>>, index) -> (index, index, index)
// CHECK: [[DIVSI2:%[0-9]+]] = arith.divsi [[BOX_DIMS2]]#2, [[BOX_ELESIZE]] : index
// CHECK: [[C0_1:%.*]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[C0_1]]], sizes: [[[BOX_DIMS1]]#1, [[BOX_DIMS2]]#1], strides: [[[DIVSI1]], [[DIVSI2]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[C0_1]]], sizes: [[[BOX_DIMS1]]#1, [[BOX_DIMS2]]#1], strides: [[[DIVSI1]], [[DIVSI2]]] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET_CAST]][[[ADDI2]], [[ADDI1]]] : memref<?x?xf32, strided<[?, ?], offset: ?>>
func.func @load_shift_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x"}) {
%c7 = arith.constant 7 : index
@@ -123,7 +123,7 @@ func.func @load_shift_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name =
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHIFT]]) dummy_scope [[DUMMY_SCOPE]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>, !fir.dscope) -> !fir.box<!fir.array<?x?x?xf32>>
// CHECK: [[REBOX:%[0-9]+]] = fir.rebox [[DECLARE]]([[SHIFT]]) : (!fir.box<!fir.array<?x?x?xf32>>, !fir.shift<3>) -> !fir.box<!fir.array<?x?x?xf32>>
// CHECK: [[BOX_ADDR:%[0-9]+]] = fir.box_addr [[REBOX]] : (!fir.box<!fir.array<?x?x?xf32>>) -> !fir.ref<!fir.array<?x?x?xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[BOX_ADDR]] : (!fir.ref<!fir.array<?x?x?xf32>>) -> memref<?x?x?xf32>
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[INDEX_CAST1]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
@@ -148,7 +148,7 @@ func.func @load_shift_2d(%arg0: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name =
// CHECK: [[BOX_DIMS3:%[0-9]+]]:3 = fir.box_dims [[REBOX]], [[C0]] : (!fir.box<!fir.array<?x?x?xf32>>, index) -> (index, index, index)
// CHECK: [[DIVSI3:%[0-9]+]] = arith.divsi [[BOX_DIMS3]]#2, [[BOX_ELESIZE]] : index
// CHECK: [[C0_1:%.*]] = arith.constant 0 : index
-// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[MARSHAL]] to offset: [[[C0_1]]], sizes: [[[BOX_DIMS1]]#1, [[BOX_DIMS2]]#1, [[BOX_DIMS3]]#1], strides: [[[DIVSI1]], [[DIVSI2]], [[DIVSI3]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+// CHECK: [[REINTERPRET_CAST:%.*]] = memref.reinterpret_cast [[CONVERT]] to offset: [[[C0_1]]], sizes: [[[BOX_DIMS1]]#1, [[BOX_DIMS2]]#1, [[BOX_DIMS3]]#1], strides: [[[DIVSI1]], [[DIVSI2]], [[DIVSI3]]] : memref<?x?x?xf32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
// CHECK: [[LOAD:%[0-9]+]] = memref.load [[REINTERPRET_CAST]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
func.func @load_shift_3d(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "x"}) {
%c10 = arith.constant 10 : index
diff --git a/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir b/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir
index 71b6b29fe451e..ac7658de7eee2 100644
--- a/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir
+++ b/flang/test/Transforms/FIRToMemRef/load-shift-static.mlir
@@ -5,16 +5,16 @@
// CHECK: [[C2:%.*]] = arith.constant 2 : index
// CHECK: [[C9:%.*]] = arith.constant 9 : index
// CHECK: [[ALLOCA:%.*]] = memref.alloca() {uniq_name = "x"} : memref<9xf32>
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<9xf32>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<9xf32>) -> !fir.ref<!fir.array<9xf32>>
// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]] : (index, index) -> !fir.shapeshift<1>
-// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9xf32>>) -> memref<9xf32>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[CONVERT1]]([[SHAPE_SHIFT]]) {uniq_name = "x"} : (!fir.ref<!fir.array<9xf32>>, !fir.shapeshift<1>) -> !fir.ref<!fir.array<9xf32>>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9xf32>>) -> memref<9xf32>
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1]] : index
// CHECK: [[SUBI2:%[0-9]+]] = arith.subi [[C2]], [[C2]] : index
// CHECK: [[ADDI1:%[0-9]+]] = arith.addi [[MULI1]], [[SUBI2]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADDI1]]] : memref<9xf32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT2]][[[ADDI1]]] : memref<9xf32>
func.func @load_shift_1d() {
%c2 = arith.constant 2 : index
%c9 = arith.constant 9 : index
@@ -38,10 +38,10 @@ func.func @load_shift_1d() {
// CHECK: [[C1:%.*]] = arith.constant 1 : index
// CHECK: [[C10:%.*]] = arith.constant 10 : index
// CHECK: [[ALLOCA:%.*]] = memref.alloca() {uniq_name = "x"} : memref<10x9xf32>
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<10x9xf32>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<10x9xf32>) -> !fir.ref<!fir.array<9x10xf32>>
// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]] : (index, index, index, index) -> !fir.shapeshift<2>
-// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFload_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10xf32>>) -> memref<10x9xf32>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[CONVERT1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFload_shift_2dEx"} : (!fir.ref<!fir.array<9x10xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<9x10xf32>>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10xf32>>) -> memref<10x9xf32>
// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
@@ -51,7 +51,7 @@ func.func @load_shift_1d() {
// CHECK: [[MULI2:%[0-9]+]] = arith.muli [[SUBI3]], [[C1_0]] : index
// CHECK: [[SUBI4:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
// CHECK: [[ADDI2:%[0-9]+]] = arith.addi [[MULI2]], [[SUBI4]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADDI2]], [[ADDI1]]] : memref<10x9xf32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT2]][[[ADDI2]], [[ADDI1]]] : memref<10x9xf32>
func.func @load_shift_2d(){
%c2 = arith.constant 2 : index
%c9 = arith.constant 9 : index
@@ -78,10 +78,10 @@ func.func @load_shift_2d(){
// CHECK: [[C3:%.*]] = arith.constant 3 : index
// CHECK: [[C8:%.*]] = arith.constant 8 : index
// CHECK: [[ALLOCA:%.*]] = memref.alloca() {bindc_name = "x", uniq_name = "x"} : memref<8x10x9xf32>
-// CHECK: [[MARSHAL1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<8x10x9xf32>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[CONVERT1:%[0-9]+]] = fir.convert [[ALLOCA]] : (memref<8x10x9xf32>) -> !fir.ref<!fir.array<9x10x8xf32>>
// CHECK: [[SHAPE_SHIFT:%[0-9]+]] = fir.shape_shift [[C2]], [[C9]], [[C1]], [[C10]], [[C3]], [[C8]] : (index, index, index, index, index, index) -> !fir.shapeshift<3>
-// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[MARSHAL1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFload_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10x8xf32>>) -> memref<8x10x9xf32>
+// CHECK: [[DECLARE:%[0-9]+]] = fir.declare [[CONVERT1]]([[SHAPE_SHIFT]]) {uniq_name = "_QFload_shift_3dEx"} : (!fir.ref<!fir.array<9x10x8xf32>>, !fir.shapeshift<3>) -> !fir.ref<!fir.array<9x10x8xf32>>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<9x10x8xf32>>) -> memref<8x10x9xf32>
// CHECK: [[C1_0:%.*]] = arith.constant 1 : index
// CHECK: [[SUBI1:%[0-9]+]] = arith.subi [[C9]], [[C2]] : index
// CHECK: [[MULI1:%[0-9]+]] = arith.muli [[SUBI1]], [[C1_0]] : index
@@ -95,7 +95,7 @@ func.func @load_shift_2d(){
// CHECK: [[MULI3:%[0-9]+]] = arith.muli [[SUBI5]], [[C1_0]] : index
// CHECK: [[SUBI6:%[0-9]+]] = arith.subi [[C3]], [[C3]] : index
// CHECK: [[ADDI3:%[0-9]+]] = arith.addi [[MULI3]], [[SUBI6]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<8x10x9xf32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT2]][[[ADDI3]], [[ADDI2]], [[ADDI1]]] : memref<8x10x9xf32>
func.func @load_shift_3d() {
%c2 = arith.constant 2 : index
%c9 = arith.constant 9 : index
diff --git a/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir b/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir
index bc351a7dd2f4e..ef561737c9e9f 100644
--- a/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir
+++ b/flang/test/Transforms/FIRToMemRef/load-static-shape.mlir
@@ -3,8 +3,8 @@
// CHECK-LABEL: func.func @load_scalar
// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<f32>) -> memref<f32>
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][] : memref<f32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<f32>) -> memref<f32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT]][] : memref<f32>
func.func @load_scalar(%arg0: !fir.ref<f32>) {
%0 = fir.undefined !fir.dscope
%1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "a"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
@@ -19,13 +19,13 @@ func.func @load_scalar(%arg0: !fir.ref<f32>) {
// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
// CHECK: [[SHAPE:%[0-9]+]] = fir.shape [[C3]] : (index) -> !fir.shape<1>
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<!fir.array<3xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<3xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3xf32>>) -> memref<3xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3xf32>>) -> memref<3xf32>
// CHECK: [[C1_0:%.+]] = arith.constant 1 : index
// CHECK: [[SUB:%[0-9]+]] = arith.subi [[C1]], [[C1_0]] : index
// CHECK: [[MUL:%[0-9]+]] = arith.muli [[SUB]], [[C1_0]] : index
// CHECK: [[SUBA:%[0-9]+]] = arith.subi [[C1_0]], [[C1_0]] : index
// CHECK: [[ADD:%[0-9]+]] = arith.addi [[MUL]], [[SUBA]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD]]] : memref<3xf32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT]][[[ADD]]] : memref<3xf32>
func.func @load_array1d_const(%arg0: !fir.ref<!fir.array<3xf32>>) {
%c1 = arith.constant 1 : index
%c3 = arith.constant 3 : index
@@ -45,7 +45,7 @@ func.func @load_array1d_const(%arg0: !fir.ref<!fir.array<3xf32>>) {
// CHECK: [[DUMMY:%[0-9]+]] = fir.undefined !fir.dscope
// CHECK: [[SHAPE:%[0-9]+]] = fir.shape [[C5]], [[C6]] : (index, index) -> !fir.shape<2>
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0([[SHAPE]]) dummy_scope [[DUMMY]] {uniq_name = "a"} : (!fir.ref<!fir.array<5x6xf32>>, !fir.shape<2>, !fir.dscope) -> !fir.ref<!fir.array<5x6xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x6xf32>>) -> memref<6x5xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x6xf32>>) -> memref<6x5xf32>
// CHECK: [[C1:%.+]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi [[C2]], [[C1]] : index
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB1]], [[C1]] : index
@@ -55,7 +55,7 @@ func.func @load_array1d_const(%arg0: !fir.ref<!fir.array<3xf32>>) {
// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB2]], [[C1]] : index
// CHECK: [[SUB2A:%[0-9]+]] = arith.subi [[C1]], [[C1]] : index
// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL2]], [[SUB2A]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD2]], [[ADD1]]] : memref<6x5xf32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT]][[[ADD2]], [[ADD1]]] : memref<6x5xf32>
func.func @load_array2d_const(%arg0: !fir.ref<!fir.array<5x6xf32>>) {
%c2 = arith.constant 2 : index
%c3 = arith.constant 3 : index
diff --git a/flang/test/Transforms/FIRToMemRef/logical.mlir b/flang/test/Transforms/FIRToMemRef/logical.mlir
index 2c0fdb7b2379a..75a9fac3e1e45 100644
--- a/flang/test/Transforms/FIRToMemRef/logical.mlir
+++ b/flang/test/Transforms/FIRToMemRef/logical.mlir
@@ -2,8 +2,8 @@
// CHECK-LABEL: func.func @load_scalar
// CHECK: [[DUMMY:%0]] = fir.undefined !fir.dscope
// CHECK-NEXT: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]]
-// CHECK-NEXT: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.logical<4>>) -> memref<i32>
-// CHECK-NEXT: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][] : memref<i32>
+// CHECK-NEXT: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.logical<4>>) -> memref<i32>
+// CHECK-NEXT: [[LOAD:%[0-9]+]] = memref.load [[CONVERT]][] : memref<i32>
// CHECK-NEXT: fir.convert [[LOAD]] : (i32) -> !fir.logical<4>
func.func @load_scalar(%arg0: !fir.ref<!fir.logical<4>>) {
%0 = fir.undefined !fir.dscope
@@ -17,9 +17,9 @@ func.func @load_scalar(%arg0: !fir.ref<!fir.logical<4>>) {
// CHECK: [[DUMMY:%0]] = fir.undefined !fir.dscope
// CHECK: [[DECLARE:%[0-9]+]] = fir.declare %arg0 dummy_scope [[DUMMY]]
// CHECK-NEXT: [[CONVERT:%[0-9]+]] = fir.convert [[CONSTTRUE]] : (i1) -> !fir.logical<4>
-// CHECK-NEXT: [[MARSHAL1:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.logical<4>>) -> memref<i32>
+// CHECK-NEXT: [[CONVERT1:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.logical<4>>) -> memref<i32>
// CHECK-NEXT: [[INT:%[0-9]+]] = fir.convert [[CONVERT]] : (!fir.logical<4>) -> i32
-// CHECK-NEXT: memref.store [[INT]], [[MARSHAL1]][] : memref<i32>
+// CHECK-NEXT: memref.store [[INT]], [[CONVERT1]][] : memref<i32>
func.func @store_scalar(%arg0: !fir.ref<!fir.logical<4>>) {
%true = arith.constant true
%0 = fir.undefined !fir.dscope
diff --git a/flang/test/Transforms/FIRToMemRef/slice.mlir b/flang/test/Transforms/FIRToMemRef/slice.mlir
index f36518cc99443..994807f591085 100644
--- a/flang/test/Transforms/FIRToMemRef/slice.mlir
+++ b/flang/test/Transforms/FIRToMemRef/slice.mlir
@@ -43,7 +43,7 @@
// CHECK: [[ADD2:%[0-9]+]] = arith.addi %[[C2]], %[[C1_1]] : index
// CHECK: scf.for %[[ARG3:.*]] = %[[C1]] to [[ADD2]] step %[[C1]] {
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<2x3xi32>>) -> !fir.ref<!fir.array<2x3xi32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x7xi32>>) -> memref<7x5xi32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<5x7xi32>>) -> memref<7x5xi32>
// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
// CHECK: %[[C1_3:.*]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[ARG3]], %[[C1_3]] : index
@@ -55,7 +55,7 @@
// CHECK: [[MUL2:%[0-9]+]] = arith.muli [[SUB3]], %[[C2]] : index
// CHECK: [[SUB4:%[0-9]+]] = arith.subi %[[C2]], %[[C1_2]] : index
// CHECK: [[ADD4:%[0-9]+]] = arith.addi [[MUL2]], [[SUB4]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD4]], [[ADD3]]] : memref<7x5xi32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT]][[[ADD4]], [[ADD3]]] : memref<7x5xi32>
func.func @slice_2d(%arg0: !fir.ref<!fir.array<5x7xi32>>, %arg1: !fir.ref<!fir.array<5x7xi32>>) {
%c4 = arith.constant 4 : index
%c2 = arith.constant 2 : index
@@ -126,7 +126,7 @@ func.func @slice_2d(%arg0: !fir.ref<!fir.array<5x7xi32>>, %arg1: !fir.ref<!fir.a
// CHECK: fir.do_loop %[[ARG3:.*]] = %[[C1]] to %[[C3]] step %[[C1]] unordered {
// CHECK: fir.do_loop %[[ARG4:.*]] = %[[C1]] to %[[C2]] step %[[C1]] unordered {
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<2x3x2xi32>>) -> !fir.ref<!fir.array<2x3x2xi32>>
-// CHECK: [[MARSHAL2:%[0-9]+]] = fir.convert [[DECLARE_B]] : (!fir.ref<!fir.array<5x7x7xi32>>) -> memref<7x7x5xi32>
+// CHECK: [[CONVERT2:%[0-9]+]] = fir.convert [[DECLARE_B]] : (!fir.ref<!fir.array<5x7x7xi32>>) -> memref<7x7x5xi32>
// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[ARG4]], %[[C1_1]] : index
@@ -143,7 +143,7 @@ func.func @slice_2d(%arg0: !fir.ref<!fir.array<5x7xi32>>, %arg1: !fir.ref<!fir.a
// CHECK: [[MUL3:%[0-9]+]] = arith.muli [[SUB5]], %[[C4]] : index
// CHECK: [[SUB6:%[0-9]+]] = arith.subi %[[C3]], %[[C1_0]] : index
// CHECK: [[ADD3:%[0-9]+]] = arith.addi [[MUL3]], [[SUB6]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL2]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<7x7x5xi32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT2]][[[ADD3]], [[ADD2]], [[ADD1]]] : memref<7x7x5xi32>
func.func @slice_3d(%arg0: !fir.ref<!fir.array<5x7x7xi32>> {fir.bindc_name = "a", llvm.nocapture}, %arg1: !fir.ref<!fir.array<5x7x7xi32>> {fir.bindc_name = "b", llvm.nocapture}) attributes {fir.internal_name = "_QPcopy"} {
%c4 = arith.constant 4 : index
%c2 = arith.constant 2 : index
@@ -185,7 +185,7 @@ func.func @slice_3d(%arg0: !fir.ref<!fir.array<5x7x7xi32>> {fir.bindc_name = "a"
// CHECK: [[ADD1:%[0-9]+]] = arith.addi %[[C3]], %[[C1_0]] : index
// CHECK: scf.for %[[ARG1:.*]] = %[[C1]] to [[ADD1]] step %[[C1]] {
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<3xi32>>) -> !fir.ref<!fir.array<3xi32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3x3xi32>>) -> memref<3x3xi32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE]] : (!fir.ref<!fir.array<3x3xi32>>) -> memref<3x3xi32>
// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[C2]], %[[C1_1]] : index
// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
@@ -193,7 +193,7 @@ func.func @slice_3d(%arg0: !fir.ref<!fir.array<5x7x7xi32>> {fir.bindc_name = "a"
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB2]], %[[C1]] : index
// CHECK: [[SUB3:%[0-9]+]] = arith.subi %[[C1]], %[[C1_1]] : index
// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL1]], [[SUB3]] : index
-// CHECK: [[LOAD:%[0-9]+]] = memref.load [[MARSHAL]][[[ADD2]], [[SUB1]]] : memref<3x3xi32>
+// CHECK: [[LOAD:%[0-9]+]] = memref.load [[CONVERT]][[[ADD2]], [[SUB1]]] : memref<3x3xi32>
func.func @extract_row(%arg0: !fir.ref<!fir.array<3x3xi32>>) {
%c1 = arith.constant 1 : index
%c2 = arith.constant 2 : index
@@ -233,7 +233,7 @@ func.func @extract_row(%arg0: !fir.ref<!fir.array<3x3xi32>>) {
// CHECK: [[ADD1:%[0-9]+]] = arith.addi %[[C10]], %[[C1_0]] : index
// CHECK: scf.for %[[ARG1:.*]] = %[[C1]] to [[ADD1]] step %[[C1]] {
// CHECK: [[BOXADDR:%[0-9]+]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>>
-// CHECK: [[MARSHAL:%[0-9]+]] = fir.convert [[DECLARE_TMP]] : (!fir.ref<!fir.array<100x5xf32>>) -> memref<5x100xf32>
+// CHECK: [[CONVERT:%[0-9]+]] = fir.convert [[DECLARE_TMP]] : (!fir.ref<!fir.array<100x5xf32>>) -> memref<5x100xf32>
// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
// CHECK: [[SUB1:%[0-9]+]] = arith.subi %[[C1]], %[[C1_1]] : index
// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
@@ -241,7 +241,7 @@ func.func @extract_row(%arg0: !fir.ref<!fir.array<3x3xi32>>) {
// CHECK: [[MUL1:%[0-9]+]] = arith.muli [[SUB2]], %[[C11]] : index
// CHECK: [[SUB3:%[0-9]+]] = arith.subi %[[C1]], %[[C1_1]] : index
// CHECK: [[ADD2:%[0-9]+]] = arith.addi [[MUL1]], [[SUB3]] : index
-// CHECK: memref.store %[[CST]], [[MARSHAL]][[[SUB1]], [[ADD2]]] : memref<5x100xf32>
+// CHECK: memref.store %[[CST]], [[CONVERT]][[[SUB1]], [[ADD2]]] : memref<5x100xf32>
func.func @extract_column(%arg0: !fir.ref<!fir.array<100x5xf32>> {fir.bindc_name = "tmp", llvm.nocapture}) attributes {fir.internal_name = "_QPextract_column"} {
%c10 = arith.constant 10 : index
%c11 = arith.constant 11 : index
@@ -282,14 +282,14 @@ func.func @extract_column(%arg0: !fir.ref<!fir.array<100x5xf32>> {fir.bindc_name
// CHECK: [[ADD1:%.*]] = arith.addi %[[ARG0]], %[[C_NEG1]] : index
// CHECK: [[SHIFT:%.*]] = fir.shift %[[C0]] : (index) -> !fir.shift<1>
// CHECK: [[BOXADDR2:%.*]] = fir.box_addr [[EMBOX]] : (!fir.box<!fir.array<7xf32>>) -> !fir.ref<!fir.array<7xf32>>
-// CHECK: [[MARSHAL:%.*]] = fir.convert [[BOXADDR2]] : (!fir.ref<!fir.array<7xf32>>) -> memref<7xf32>
+// CHECK: [[CONVERT:%.*]] = fir.convert [[BOXADDR2]] : (!fir.ref<!fir.array<7xf32>>) -> memref<7xf32>
// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
// CHECK: [[ADD2:%.*]] = arith.addi %[[ARG0]], %[[C_NEG1]] : index
// CHECK: [[SUB1:%.*]] = arith.subi [[ADD2]], %[[C0]] : index
// CHECK: [[MUL1:%.*]] = arith.muli [[SUB1]], %[[C1_0]] : index
// CHECK: [[SUB2:%[0-9]+]] = arith.subi %[[C0]], %[[C0]] : index
// CHECK: [[ADD3:%.*]] = arith.addi [[MUL1]], [[SUB2]] : index
-// CHECK: [[LOADVAL:%.*]] = memref.load [[MARSHAL]][[[ADD3]]] : memref<7xf32>
+// CHECK: [[LOADVAL:%.*]] = memref.load [[CONVERT]][[[ADD3]]] : memref<7xf32>
func.func @noslice() {
%c7 = arith.constant 7 : index
%c-1 = arith.constant -1 : index
@@ -317,7 +317,7 @@ func.func @noslice() {
// CHECK: %[[C_NEG6:.*]] = arith.constant -6 : index
// CHECK: %[[C5:.*]] = arith.constant 5 : index
// CHECK: %[[ALLOCA:.*]] = memref.alloca() : memref<i32>
-// CHECK: %[[MARSHAL1:.*]] = fir.convert %[[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
+// CHECK: %[[CONVERT1:.*]] = fir.convert %[[ALLOCA]] : (memref<i32>) -> !fir.ref<i32>
// CHECK: %[[DUMMY_SCOPE:[0-9]+]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[ADDR:[0-9]+]] = fir.address_of(@_QFFsECindex) : !fir.ref<!fir.array<5xi32>>
// CHECK: %[[SHAPE:[0-9]+]] = fir.shape %[[C5]] : (index) -> !fir.shape<1>
@@ -333,14 +333,14 @@ func.func @noslice() {
// CHECK: %[[C1_0:.*]] = arith.constant 1 : index
// CHECK: %[[ADD2:[0-9]+]] = arith.addi %[[SELECT]], %[[C1_0]] : index
// CHECK: scf.for %[[ARG0:.*]] = %[[C1]] to %[[ADD2]] step %[[C1]] {
-// CHECK: %[[MARSHAL2:.*]] = fir.convert %[[DECLARE]] : (!fir.ref<!fir.array<5xi32>>) -> memref<5xi32>
+// CHECK: %[[CONVERT2:.*]] = fir.convert %[[DECLARE]] : (!fir.ref<!fir.array<5xi32>>) -> memref<5xi32>
// CHECK: %[[C1_1:.*]] = arith.constant 1 : index
// CHECK: %[[C1_2:.*]] = arith.constant 1 : index
// CHECK: %[[SUB1:[0-9]+]] = arith.subi %[[ARG0]], %[[C1_2]] : index
// CHECK: %[[MUL1:[0-9]+]] = arith.muli %[[SUB1]], %[[C_NEG1]] : index
// CHECK: %[[SUB2:[0-9]+]] = arith.subi %[[C5]], %[[C1_1]] : index
// CHECK: %[[ADD3:[0-9]+]] = arith.addi %[[MUL1]], %[[SUB2]] : index
-// CHECK: %[[LOAD2:[0-9]+]] = memref.load %[[MARSHAL2]][%[[ADD3]]] : memref<5xi32>
+// CHECK: %[[LOAD2:[0-9]+]] = memref.load %[[CONVERT2]][%[[ADD3]]] : memref<5xi32>
func.func @array_coor_slice() attributes {fir.bindc_name = "tf4a", noinline} {
%c0 = arith.constant 0 : index
%c-1 = arith.constant -1 : index
More information about the flang-commits
mailing list