[flang-commits] [flang] [flang] FIR memory ops lowering to MemRef dialect (PR #173507)
via flang-commits
flang-commits at lists.llvm.org
Wed Dec 24 11:43:24 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-codegen
@llvm/pr-subscribers-flang-fir-hlfir
Author: Susan Tan (ス-ザン タン) (SusanTan)
<details>
<summary>Changes</summary>
This patch introduces FIRToMemRef, a lowering pass that lowers FIR memory ops to MemRef dialect, including slices and shifts handling. Since we use `fir.convert` to convert between memref and fir types such that partial lowering is possible, we also added a customized `fir.convert` implementation that handles memref type lowering.
---
Patch is 162.97 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173507.diff
25 Files Affected:
- (added) flang/include/flang/Optimizer/Transforms/FIRToMemRefTypeConverter.h (+226)
- (modified) flang/include/flang/Optimizer/Transforms/Passes.td (+12)
- (modified) flang/lib/Optimizer/CodeGen/CodeGen.cpp (+53-7)
- (modified) flang/lib/Optimizer/Transforms/CMakeLists.txt (+1)
- (added) flang/lib/Optimizer/Transforms/FIRToMemRef.cpp (+1171)
- (added) flang/test/Fir/FIRToMemRef/alloca.mlir (+97)
- (added) flang/test/Fir/FIRToMemRef/array-coor-op.mlir (+47)
- (added) flang/test/Fir/FIRToMemRef/complex.mlir (+18)
- (added) flang/test/Fir/FIRToMemRef/cuda-alloca.mlir (+14)
- (added) flang/test/Fir/FIRToMemRef/derived-types.mlir (+31)
- (added) flang/test/Fir/FIRToMemRef/index.mlir (+31)
- (added) flang/test/Fir/FIRToMemRef/load-dynamic-shape.mlir (+130)
- (added) flang/test/Fir/FIRToMemRef/load-shift-dynamic.mlir (+169)
- (added) flang/test/Fir/FIRToMemRef/load-shift-static.mlir (+114)
- (added) flang/test/Fir/FIRToMemRef/load-static-shape.mlir (+70)
- (added) flang/test/Fir/FIRToMemRef/logical.mlir (+30)
- (added) flang/test/Fir/FIRToMemRef/no-declare.mlir (+51)
- (added) flang/test/Fir/FIRToMemRef/reject-conversions.mlir (+29)
- (added) flang/test/Fir/FIRToMemRef/replace.mlir (+29)
- (added) flang/test/Fir/FIRToMemRef/slice.mlir (+372)
- (added) flang/test/Fir/FIRToMemRef/store-dynamic-shape.mlir (+129)
- (added) flang/test/Fir/FIRToMemRef/store-shift-static.mlir (+118)
- (added) flang/test/Fir/FIRToMemRef/store-static-shape.mlir (+75)
- (added) flang/test/Fir/FIRToMemRef/tbaa-tag.mlir (+44)
- (modified) flang/test/Fir/convert-memref-codegen.mlir (+25-4)
``````````diff
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::Sha...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/173507
More information about the flang-commits
mailing list