llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Ming Yan (NexMing)

<details>
<summary>Changes</summary>

This patch begins a long-term effort to establish an incremental FIR to MLIR 
lowering path while preserving the existing FIR to LLVM pipeline. It introduces 
the core conversion infrastructure and demonstrates the approach with example 
conversions such as convert `fir.load` to `memref.load`. The new lowering can 
coexist with the current pipeline, enabling mixed-mode lowering without 
affecting existing behavior. Future patches will extend the coverage to more 
operations and types.

---

Patch is 34.87 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/168703.diff


16 Files Affected:

- (modified) clang/include/clang/Options/Options.td (+5) 
- (modified) clang/lib/Driver/ToolChains/Flang.cpp (+1) 
- (modified) flang/include/flang/Lower/LoweringOptions.def (+3) 
- (modified) flang/include/flang/Optimizer/Passes/Pipelines.h (+3) 
- (modified) flang/include/flang/Optimizer/Support/InitFIR.h (+8-1) 
- (modified) flang/include/flang/Optimizer/Transforms/Passes.td (+11) 
- (modified) flang/include/flang/Tools/CrossToolHelpers.h (+1) 
- (modified) flang/lib/Frontend/CompilerInvocation.cpp (+4) 
- (modified) flang/lib/Frontend/FrontendActions.cpp (+1) 
- (modified) flang/lib/Optimizer/CodeGen/CodeGen.cpp (+35-2) 
- (modified) flang/lib/Optimizer/Passes/Pipelines.cpp (+18-5) 
- (modified) flang/lib/Optimizer/Transforms/CMakeLists.txt (+1) 
- (added) flang/lib/Optimizer/Transforms/ConvertFIRToMLIR.cpp (+238) 
- (modified) flang/test/Driver/frontend-forwarding.f90 (+2) 
- (modified) flang/test/Fir/convert-to-llvm.fir (+75) 
- (added) flang/test/Fir/convert-to-mlir.fir (+135) 


``````````diff
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index cda11fdc94230..cd8409de8c5a9 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -7217,6 +7217,11 @@ def flang_deprecated_no_hlfir : Flag<["-"], 
"flang-deprecated-no-hlfir">,
   Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>,
   HelpText<"Do not use HLFIR lowering (deprecated)">;
 
+def flang_experimental_lower_through_mlir
+  : Flag<["-"], "flang-experimental-lower-through-mlir">,
+    Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>,
+    HelpText<"Lower form FIR through MLIR to LLVM (experimental)">;
+
 
//===----------------------------------------------------------------------===//
 // FLangOption + CoreOption + NoXarchOption
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index 270904de544d6..e294ac59af73d 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -222,6 +222,7 @@ void Flang::addCodegenOptions(const ArgList &Args,
       {options::OPT_fdo_concurrent_to_openmp_EQ,
        options::OPT_flang_experimental_hlfir,
        options::OPT_flang_deprecated_no_hlfir,
+       options::OPT_flang_experimental_lower_through_mlir,
        options::OPT_fno_ppc_native_vec_elem_order,
        options::OPT_fppc_native_vec_elem_order, options::OPT_finit_global_zero,
        options::OPT_fno_init_global_zero, options::OPT_frepack_arrays,
diff --git a/flang/include/flang/Lower/LoweringOptions.def 
b/flang/include/flang/Lower/LoweringOptions.def
index 39f197d8d35c8..01fc96b78df50 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -38,6 +38,9 @@ ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)
 /// (i.e. wraps around as two's complement). Off by default.
 ENUM_LOWERINGOPT(IntegerWrapAround, unsigned, 1, 0)
 
+/// If true, lower form FIR through MLIR to LLVM
+ENUM_LOWERINGOPT(LowerThroughMLIR, unsigned, 1, 0)
+
 /// If true (default), follow Fortran 2003 rules for (re)allocating
 /// the allocatable on the left side of the intrinsic assignment,
 /// if LHS and RHS have mismatching shapes/types.
diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h 
b/flang/include/flang/Optimizer/Passes/Pipelines.h
index 70b9341347244..e1e990bfd1c01 100644
--- a/flang/include/flang/Optimizer/Passes/Pipelines.h
+++ b/flang/include/flang/Optimizer/Passes/Pipelines.h
@@ -18,10 +18,13 @@
 #include "flang/Optimizer/Passes/CommandLineOpts.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 #include "flang/Tools/CrossToolHelpers.h"
+#include "mlir/Conversion/AffineToStandard/AffineToStandard.h"
+#include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h"
 #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
 #include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Dialect/MemRef/Transforms/Passes.h"
 #include "mlir/Dialect/OpenMP/Transforms/Passes.h"
 #include "mlir/Pass/PassManager.h"
 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h 
b/flang/include/flang/Optimizer/Support/InitFIR.h
index 67e9287ddad4f..184e2aa141d85 100644
--- a/flang/include/flang/Optimizer/Support/InitFIR.h
+++ b/flang/include/flang/Optimizer/Support/InitFIR.h
@@ -32,6 +32,8 @@
 #include "mlir/Dialect/LLVMIR/NVVMDialect.h"
 #include "mlir/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.h"
 #include "mlir/Dialect/Math/IR/Math.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/MemRef/Transforms/Passes.h"
 #include "mlir/Dialect/OpenACC/OpenACC.h"
 #include "mlir/Dialect/OpenACC/Transforms/Passes.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
@@ -54,7 +56,8 @@ namespace fir::support {
       mlir::NVVM::NVVMDialect, mlir::gpu::GPUDialect,                          
\
       mlir::index::IndexDialect, mif::MIFDialect
 
-#define FLANG_CODEGEN_DIALECT_LIST FIRCodeGenDialect, mlir::LLVM::LLVMDialect
+#define FLANG_CODEGEN_DIALECT_LIST                                             
\
+  FIRCodeGenDialect, mlir::memref::MemRefDialect, mlir::LLVM::LLVMDialect
 
 // The definitive list of dialects used by flang.
 #define FLANG_DIALECT_LIST                                                     
\
@@ -129,7 +132,11 @@ inline void registerMLIRPassesForFortranTools() {
   mlir::affine::registerAffineLoopTilingPass();
   mlir::affine::registerAffineDataCopyGenerationPass();
 
+  mlir::registerMem2RegPass();
+  mlir::memref::registerMemRefPasses();
+
   mlir::registerLowerAffinePass();
+  mlir::registerReconcileUnrealizedCastsPass();
 }
 
 /// Register the interfaces needed to lower to LLVM IR.
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td 
b/flang/include/flang/Optimizer/Transforms/Passes.td
index bb2509b1747d5..0bf1537b2215c 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -87,6 +87,17 @@ def FIRToSCFPass : Pass<"fir-to-scf"> {
   ];
 }
 
+def ConvertFIRToMLIRPass : Pass<"fir-to-mlir", "mlir::ModuleOp"> {
+  let summary = "Convert the FIR dialect module to MLIR standard dialects.";
+  let description = [{
+    Convert the FIR dialect module to MLIR standard dialects.
+  }];
+  let dependentDialects = [
+    "fir::FIROpsDialect", "fir::FIRCodeGenDialect", "mlir::scf::SCFDialect",
+    "mlir::memref::MemRefDialect", "mlir::affine::AffineDialect"
+  ];
+}
+
 def AnnotateConstantOperands : Pass<"annotate-constant"> {
   let summary = "Annotate constant operands to all FIR operations";
   let description = [{
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h 
b/flang/include/flang/Tools/CrossToolHelpers.h
index e964882ef6dac..0dcb99e1eb5b1 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -137,6 +137,7 @@ struct MLIRToLLVMPassPipelineConfig : public 
FlangEPCallBacks {
   bool EnableOpenMP = false; ///< Enable OpenMP lowering.
   bool EnableOpenMPSimd = false; ///< Enable OpenMP simd-only mode.
   bool SkipConvertComplexPow = false; ///< Do not run complex pow conversion.
+  bool LowerThroughMLIR = false; ///< Lower form FIR through MLIR to LLVM
   std::string InstrumentFunctionEntry =
       ""; ///< Name of the instrument-function that is called on each
           ///< function-entry
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index 893121fe01f27..8c3fde0a27153 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1580,6 +1580,10 @@ bool CompilerInvocation::createFromArgs(
     invoc.loweringOpts.setLowerToHighLevelFIR(false);
   }
 
+  // -flang-experimental-lower-through-mlir
+  invoc.loweringOpts.setLowerThroughMLIR(
+      args.hasArg(clang::options::OPT_flang_experimental_lower_through_mlir));
+
   // -fno-ppc-native-vector-element-order
   if (args.hasArg(clang::options::OPT_fno_ppc_native_vec_elem_order)) {
     invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);
diff --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 159d08a2797b3..0cb241f209522 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -769,6 +769,7 @@ void CodeGenAction::generateLLVMIR() {
     config.NSWOnLoopVarInc = false;
 
   config.ComplexRange = opts.getComplexRange();
+  config.LowerThroughMLIR = invoc.getLoweringOpts().getLowerThroughMLIR();
 
   // Create the pass pipeline
   fir::createMLIRToLLVMPassPipeline(pm, config, getCurrentFile());
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp 
b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index f96d45d3f6b66..1f52cd4011b7a 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1008,6 +1008,29 @@ struct ConvertOpConversion : public 
fir::FIROpConversion<fir::ConvertOp> {
         rewriter.replaceOpWithNewOp<mlir::LLVM::BitcastOp>(convert, toTy, op0);
         return mlir::success();
       }
+      // Pointer to MemRef conversion.
+      if (mlir::isa<mlir::MemRefType>(toFirTy)) {
+        auto dstMemRef = mlir::MemRefDescriptor::poison(rewriter, loc, toTy);
+        dstMemRef.setAlignedPtr(rewriter, loc, op0);
+        dstMemRef.setOffset(
+            rewriter, loc,
+            createIndexAttrConstant(rewriter, loc, getIndexType(), 0));
+        rewriter.replaceOp(convert, {dstMemRef});
+        return mlir::success();
+      }
+    } else if (mlir::isa<mlir::MemRefType>(fromFirTy) &&
+               mlir::isa<mlir::LLVM::LLVMPointerType>(toTy)) {
+      // MemRef to pointer conversion.
+      auto srcMemRef = mlir::MemRefDescriptor(op0);
+      mlir::Type elementType = typeConverter->convertType(
+          mlir::cast<mlir::MemRefType>(fromFirTy).getElementType());
+      mlir::Value srcBasePtr = srcMemRef.alignedPtr(rewriter, loc);
+      mlir::Value srcOffset = srcMemRef.offset(rewriter, loc);
+      mlir::Value srcPtr =
+          mlir::LLVM::GEPOp::create(rewriter, loc, srcBasePtr.getType(),
+                                    elementType, srcBasePtr, srcOffset);
+      rewriter.replaceOp(convert, srcPtr);
+      return mlir::success();
     }
     return emitError(loc) << "cannot convert " << fromTy << " to " << toTy;
   }
@@ -3521,6 +3544,13 @@ struct SelectCaseOpConversion : public 
fir::FIROpConversion<fir::SelectCaseOp> {
     auto loc = caseOp.getLoc();
     for (unsigned t = 0; t != conds; ++t) {
       mlir::Block *dest = caseOp.getSuccessor(t);
+      std::optional<mlir::TypeConverter::SignatureConversion> conversion =
+          getTypeConverter()->convertBlockSignature(dest);
+      if (!conversion) {
+        return rewriter.notifyMatchFailure(caseOp,
+                                           "could not compute block 
signature");
+      }
+      dest = rewriter.applySignatureConversion(dest, *conversion);
       std::optional<mlir::ValueRange> destOps =
           caseOp.getSuccessorOperands(adaptor.getOperands(), t);
       std::optional<mlir::ValueRange> cmpOps =
@@ -4326,7 +4356,7 @@ class FIRToLLVMLowering
     target.addLegalDialect<mlir::gpu::GPUDialect>();
 
     // required NOPs for applying a full conversion
-    target.addLegalOp<mlir::ModuleOp>();
+    target.addLegalOp<mlir::ModuleOp, mlir::UnrealizedConversionCastOp>();
 
     // If we're on Windows, we might need to rename some libm calls.
     bool isMSVC = fir::getTargetTriple(mod).isOSMSVCRT();
@@ -4346,9 +4376,12 @@ class FIRToLLVMLowering
           });
     }
 
+    mlir::ConversionConfig config;
+    config.buildMaterializations = false;
+
     // apply the patterns
     if (mlir::failed(mlir::applyFullConversion(getModule(), target,
-                                               std::move(pattern)))) {
+                                               std::move(pattern), config))) {
       signalPassFailure();
     }
 
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp 
b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 103e736accca0..3e233e07228ed 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -109,6 +109,21 @@ void addDebugInfoPass(mlir::PassManager &pm,
 
 void addFIRToLLVMPass(mlir::PassManager &pm,
                       const MLIRToLLVMPassPipelineConfig &config) {
+  if (disableFirToLlvmIr)
+    return;
+
+  if (config.LowerThroughMLIR) {
+    pm.addPass(createConvertFIRToMLIRPass());
+    pm.addPass(mlir::memref::createFoldMemRefAliasOpsPass());
+    pm.addPass(mlir::createMem2Reg());
+    pm.addPass(mlir::createCSEPass());
+    pm.addPass(mlir::createCanonicalizerPass());
+    pm.addPass(mlir::memref::createExpandOpsPass());
+    pm.addPass(mlir::memref::createExpandStridedMetadataPass());
+    pm.addPass(mlir::createLowerAffinePass());
+    pm.addPass(mlir::createFinalizeMemRefToLLVMConversionPass());
+  }
+
   fir::FIRToLLVMPassOptions options;
   options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
   options.skipExternalRttiDefinition = skipExternalRttiDefinition;
@@ -117,13 +132,11 @@ void addFIRToLLVMPass(mlir::PassManager &pm,
   options.typeDescriptorsRenamedForAssembly =
       !disableCompilerGeneratedNamesConversion;
   options.ComplexRange = config.ComplexRange;
-  addPassConditionally(pm, disableFirToLlvmIr,
-                       [&]() { return fir::createFIRToLLVMPass(options); });
+  pm.addPass(fir::createFIRToLLVMPass(options));
+
   // The dialect conversion framework may leave dead unrealized_conversion_cast
   // ops behind, so run reconcile-unrealized-casts to clean them up.
-  addPassConditionally(pm, disableFirToLlvmIr, [&]() {
-    return mlir::createReconcileUnrealizedCastsPass();
-  });
+  pm.addPass(mlir::createReconcileUnrealizedCastsPass());
 }
 
 void addLLVMDialectToLLVMPass(mlir::PassManager &pm,
diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt 
b/flang/lib/Optimizer/Transforms/CMakeLists.txt
index 0388439f89a54..a6423b3dea5a9 100644
--- a/flang/lib/Optimizer/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt
@@ -36,6 +36,7 @@ add_flang_library(FIRTransforms
   SimplifyFIROperations.cpp
   OptimizeArrayRepacking.cpp
   ConvertComplexPow.cpp
+  ConvertFIRToMLIR.cpp
   MIFOpConversion.cpp
 
   DEPENDS
diff --git a/flang/lib/Optimizer/Transforms/ConvertFIRToMLIR.cpp 
b/flang/lib/Optimizer/Transforms/ConvertFIRToMLIR.cpp
new file mode 100644
index 0000000000000..1470f78dc4e9c
--- /dev/null
+++ b/flang/lib/Optimizer/Transforms/ConvertFIRToMLIR.cpp
@@ -0,0 +1,238 @@
+//===-- ConvertFIRToMLIR.cpp 
----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Dialect/FIRCG/CGOps.h"
+#include "flang/Optimizer/Dialect/FIRDialect.h"
+#include "flang/Optimizer/Transforms/Passes.h"
+#include "mlir/Dialect/Affine/IR/AffineOps.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace fir {
+#define GEN_PASS_DEF_CONVERTFIRTOMLIRPASS
+#include "flang/Optimizer/Transforms/Passes.h.inc"
+} // namespace fir
+
+namespace {
+class ConvertFIRToMLIRPass
+    : public fir::impl::ConvertFIRToMLIRPassBase<ConvertFIRToMLIRPass> {
+public:
+  void runOnOperation() override;
+};
+
+class FIRLoadOpLowering : public mlir::OpConversionPattern<fir::LoadOp> {
+public:
+  using mlir::OpConversionPattern<fir::LoadOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::LoadOp op, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    if (!getTypeConverter()->convertType(op.getMemref()))
+      return mlir::failure();
+
+    rewriter.replaceOpWithNewOp<mlir::memref::LoadOp>(op, adaptor.getMemref(),
+                                                      mlir::ValueRange{});
+    return mlir::success();
+  }
+};
+
+class FIRStoreOpLowering : public mlir::OpConversionPattern<fir::StoreOp> {
+public:
+  using mlir::OpConversionPattern<fir::StoreOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::StoreOp op, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    if (!getTypeConverter()->convertType(op.getMemref()))
+      return mlir::failure();
+
+    rewriter.replaceOpWithNewOp<mlir::memref::StoreOp>(
+        op, adaptor.getValue(), adaptor.getMemref(), mlir::ValueRange{});
+    return mlir::success();
+  }
+};
+
+class FIRConvertOpLowering : public mlir::OpConversionPattern<fir::ConvertOp> {
+public:
+  using mlir::OpConversionPattern<fir::ConvertOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::ConvertOp op, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    auto srcType = getTypeConverter()->convertType(op.getValue().getType());
+    auto dstType = getTypeConverter()->convertType(op.getType());
+
+    if (!srcType || !dstType)
+      return mlir::failure();
+
+    auto srcVal = adaptor.getValue();
+
+    if (srcType == dstType) {
+      rewriter.replaceOp(op, mlir::ValueRange{srcVal});
+    } else if (srcType.isIntOrIndex() && dstType.isIntOrIndex()) {
+      if (srcType.isIndex() || dstType.isIndex()) {
+        rewriter.replaceOpWithNewOp<mlir::arith::IndexCastOp>(op, dstType,
+                                                              srcVal);
+      } else if (srcType.getIntOrFloatBitWidth() <
+                 dstType.getIntOrFloatBitWidth()) {
+        rewriter.replaceOpWithNewOp<mlir::arith::ExtSIOp>(op, dstType, srcVal);
+      } else {
+        rewriter.replaceOpWithNewOp<mlir::arith::TruncIOp>(op, dstType, 
srcVal);
+      }
+    } else if (srcType.isFloat() && dstType.isFloat()) {
+      if (srcType.getIntOrFloatBitWidth() < dstType.getIntOrFloatBitWidth()) {
+        rewriter.replaceOpWithNewOp<mlir::arith::ExtFOp>(op, dstType, srcVal);
+      } else {
+        rewriter.replaceOpWithNewOp<mlir::arith::TruncFOp>(op, dstType, 
srcVal);
+      }
+    } else {
+      return mlir::failure();
+    }
+
+    return mlir::success();
+  }
+};
+
+class FIRAllocOpLowering : public mlir::OpConversionPattern<fir::AllocaOp> {
+public:
+  using mlir::OpConversionPattern<fir::AllocaOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::AllocaOp op, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    if (!mlir::MemRefType::isValidElementType(op.getAllocatedType()) ||
+        op.hasLenParams())
+      return mlir::failure();
+
+    auto dstType = getTypeConverter()->convertType(op.getType());
+    auto allocaOp = mlir::memref::AllocaOp::create(
+        rewriter, op.getLoc(),
+        mlir::MemRefType::get({}, op.getAllocatedType()));
+    allocaOp->setAttrs(op->getAttrs());
+    rewriter.replaceOpWithNewOp<mlir::memref::CastOp>(op, dstType, allocaOp);
+    return mlir::success();
+  }
+};
+
+class FIRXArrayCoorOpLowering
+    : public mlir::OpConversionPattern<fir::cg::XArrayCoorOp> {
+public:
+  using mlir::OpConversionPattern<fir::cg::XArrayCoorOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(fir::cg::XArrayCoorOp op, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    if (!getTypeConverter()->convertType(op.getMemref()))
+      return mlir::failure();
+
+    mlir::Location loc = op.getLoc();
+    auto metadata = mlir::memref::ExtractStridedMetadataOp::create(
+        rewriter, loc, adaptor.getMemref());
+    auto base = metadata.getBaseBuffer();
+    auto offset = metadata.getOffset();
+    mlir::ValueRange shape = adaptor.getShape();
+    unsigned rank = op.getRank();
+
+    assert(rank > 0 && "expected rank to be greater than zero");
+
+    auto sizes = llvm::to_vector_of<mlir::OpFoldResult>(llvm::reverse(shape));
+    mlir::SmallVector<mlir::OpFoldResult> strides(rank);
+
+    strides[rank - 1] = rewriter.getIndexAttr(1);
+    mlir::Value stride = mlir::arith::ConstantIndexOp::create(rewriter, loc, 
1);
+    for (unsigned i = 1; i < rank; ++i) {
+      stride = mlir::arith::MulIOp::create(rewriter, loc, stride, shape[i - 
1]);
+      strides[rank - 1 - i] = stride;
+    }
+
+    mlir::Value memref = mlir::memref::ReinterpretCastOp::create(
+        rewriter, loc, base, offset, sizes, strides);
+
+    mlir::SmallVector<mlir::OpFoldResult> oneAttrs(rank,
+                                                   rewriter.getIndexAttr(1));
+    auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1);
+    auto offsets = llvm::map_to_vector(
+        llvm::reverse(adaptor.getIndices()),
+        [&](mlir::Value idx) -> mlir::OpFoldResult {
+          if (idx.getType().isInteger())
+            idx = mlir::arith::IndexCastOp::create(
+                rewriter, loc, rewriter.getIndexType(), idx);
+
+          assert(idx.getType().isIndex() && "expected index type");
+          idx = mlir::arith::SubIOp...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/168703
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [clang] [... Ming Yan via cfe-commits
    • [cla... via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... via cfe-commits
    • [cla... via cfe-commits
    • [cla... via cfe-commits
    • [cla... Ming Yan via cfe-commits
    • [cla... Ivan Butygin via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits
    • [cla... Valentin Clement バレンタイン クレメン via cfe-commits

Reply via email to