[flang-commits] [flang] [flang] Register memref-to-llvm patterns in FIRToLLVMLowering (PR #234305)
via flang-commits
flang-commits at lists.llvm.org
Thu Oct 22 11:54:37 PDT 2026
https://github.com/jon-gibney updated https://github.com/llvm/llvm-project/pull/234305
>From 558e75dd4b7572fa903ecd8927b19fdc2504f211 Mon Sep 17 00:00:00 2001
From: Jon Gibney <jonathon.gibney at hpe.com>
Date: Wed, 21 Oct 2026 13:09:39 -0500
Subject: [PATCH 1/3] [flang] Register memref-to-llvm patterns in
FIRToLLVMLowering With fir-opt --fir-to-scf --fir-to-memref mlir-opt
--raise-scf-to-affine --affine-raise-from-memref we can get from FIR to
affine and do restructuring in that form. However, doing fir-opt
--lower-affine leaves memref ops that fir-opt --fir-to-llvm-ir couldn't
legalize, as mentioned in
https://discourse.llvm.org/t/flang-affine-linearized-array-access-in-promote-to-affine-causes-false-dependence-and-blocks-loop-tiling/89927/7
This adds the memref-to-llvm patterns to FIRToLLVMLowering to fix
that.
---
flang/lib/Optimizer/CodeGen/CMakeLists.txt | 1 +
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 3 ++
flang/test/Fir/memref-ops-codegen.mlir | 50 ++++++++++++++++++++++
3 files changed, 54 insertions(+)
create mode 100644 flang/test/Fir/memref-ops-codegen.mlir
diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
index c3cb3ca4b3ebfd..0ed85c1cc79880 100644
--- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt
+++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
@@ -44,6 +44,7 @@ add_flang_library(FIRCodeGen
MLIRMathToLibm
MLIRMathToNVVM
MLIRMathToROCDL
+ MLIRMemRefToLLVM
MLIROpenMPToLLVMConversion
MLIROpenACCDialect
MLIRBuiltinToLLVMIRTranslation
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index d0f522a1754727..17816af26e4bd5 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -49,6 +49,7 @@
#include "mlir/Conversion/MathToLibm/MathToLibm.h"
#include "mlir/Conversion/MathToNVVM/MathToNVVM.h"
#include "mlir/Conversion/MathToROCDL/MathToROCDL.h"
+#include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h"
#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
#include "mlir/Conversion/UBToLLVM/UBToLLVM.h"
#include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h"
@@ -5278,6 +5279,8 @@ class FIRToLLVMLowering
mlir::index::populateIndexToLLVMConversionPatterns(typeConverter, pattern);
mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern);
mlir::ub::populateUBToLLVMConversionPatterns(typeConverter, pattern);
+ mlir::populateFinalizeMemRefToLLVMConversionPatterns(typeConverter,
+ pattern);
// Flang specific overloads for OpenMP operations, to allow for special
// handling of things like Box types.
diff --git a/flang/test/Fir/memref-ops-codegen.mlir b/flang/test/Fir/memref-ops-codegen.mlir
new file mode 100644
index 00000000000000..cd2367143ea7f2
--- /dev/null
+++ b/flang/test/Fir/memref-ops-codegen.mlir
@@ -0,0 +1,50 @@
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" --split-input-file %s | FileCheck %s
+
+// Test that memref dialect operations, as produced by fir-to-memref and
+// lower-affine, are lowered together with the fir.convert ops that bridge
+// !fir.ref and memref values.
+
+// CHECK-LABEL: llvm.func @load_scalar(
+// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr) -> i32 {
+// CHECK: %[[ALIGNED:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)>
+// CHECK: %[[VAL:.*]] = llvm.load %[[ALIGNED]] : !llvm.ptr -> i32
+// CHECK: llvm.return %[[VAL]] : i32
+// CHECK-NOT: memref.
+func.func @load_scalar(%arg0: !fir.ref<i32>) -> i32 {
+ %0 = fir.convert %arg0 : (!fir.ref<i32>) -> memref<i32>
+ %1 = memref.load %0[] : memref<i32>
+ return %1 : i32
+}
+
+// -----
+
+// CHECK-LABEL: llvm.func @store_scalar(
+// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr, %[[VAL:.*]]: f32) {
+// CHECK: %[[ALIGNED:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)>
+// CHECK: llvm.store %[[VAL]], %[[ALIGNED]] : f32, !llvm.ptr
+// CHECK-NOT: memref.
+func.func @store_scalar(%arg0: !fir.ref<f32>, %arg1: f32) {
+ %0 = fir.convert %arg0 : (!fir.ref<f32>) -> memref<f32>
+ memref.store %arg1, %0[] : memref<f32>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: llvm.func @load_store_static_2d(
+// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr, %[[I:.*]]: i64, %[[J:.*]]: i64) {
+// CHECK: %[[MUL0:.*]] = llvm.mul %[[I]], %{{.*}}
+// CHECK: %[[ADD0:.*]] = llvm.add %[[MUL0]], %[[J]]
+// CHECK: %[[SRC:.*]] = llvm.getelementptr {{.*}}[%[[ADD0]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
+// CHECK: %[[VAL:.*]] = llvm.load %[[SRC]] : !llvm.ptr -> f32
+// CHECK: %[[MUL1:.*]] = llvm.mul %[[J]], %{{.*}}
+// CHECK: %[[ADD1:.*]] = llvm.add %[[MUL1]], %[[I]]
+// CHECK: %[[DST:.*]] = llvm.getelementptr {{.*}}[%[[ADD1]]] : (!llvm.ptr, i64) -> !llvm.ptr, f32
+// CHECK: llvm.store %[[VAL]], %[[DST]] : f32, !llvm.ptr
+// CHECK-NOT: memref.
+func.func @load_store_static_2d(%arg0: !fir.ref<!fir.array<4x8xf32>>, %i: index, %j: index) {
+ %0 = fir.convert %arg0 : (!fir.ref<!fir.array<4x8xf32>>) -> memref<4x8xf32>
+ %1 = memref.load %0[%i, %j] : memref<4x8xf32>
+ memref.store %1, %0[%j, %i] : memref<4x8xf32>
+ return
+}
>From 27802bfeca24f7e40a7e29146c9c751a5c07624f Mon Sep 17 00:00:00 2001
From: Jon Gibney <jonathon.gibney at hpe.com>
Date: Thu, 22 Oct 2026 13:28:16 -0500
Subject: [PATCH 2/3] Pass the symbol table
---
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 17816af26e4bd5..3d1e7602537098 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -5279,8 +5279,8 @@ class FIRToLLVMLowering
mlir::index::populateIndexToLLVMConversionPatterns(typeConverter, pattern);
mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern);
mlir::ub::populateUBToLLVMConversionPatterns(typeConverter, pattern);
- mlir::populateFinalizeMemRefToLLVMConversionPatterns(typeConverter,
- pattern);
+ mlir::populateFinalizeMemRefToLLVMConversionPatterns(typeConverter, pattern,
+ &symbolTables);
// Flang specific overloads for OpenMP operations, to allow for special
// handling of things like Box types.
>From c49e081aa54a64e3b37ddcd7444e2dba6e676c07 Mon Sep 17 00:00:00 2001
From: Jon Gibney <jonathon.gibney at hpe.com>
Date: Thu, 22 Oct 2026 13:53:17 -0500
Subject: [PATCH 3/3] Put under an option
---
flang/include/flang/Optimizer/CodeGen/CGPasses.td | 4 +++-
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 5 +++--
flang/test/Fir/memref-ops-codegen.mlir | 7 +++++--
3 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/flang/include/flang/Optimizer/CodeGen/CGPasses.td b/flang/include/flang/Optimizer/CodeGen/CGPasses.td
index 6f0ae6588c2de4..ac16f4111630e2 100644
--- a/flang/include/flang/Optimizer/CodeGen/CGPasses.td
+++ b/flang/include/flang/Optimizer/CodeGen/CGPasses.td
@@ -51,7 +51,9 @@ def FIRToLLVMLowering : Pass<"fir-to-llvm-ir", "mlir::ModuleOp"> {
"allocations marked with the unified heap allocation mode.">,
Option<"managedHeapAllocSuffix", "managed-heap-alloc-suffix", "std::string",
/*default=*/"", "Suffix of the allocator entry points used for "
- "allocations marked with the managed heap allocation mode.">
+ "allocations marked with the managed heap allocation mode.">,
+ Option<"lowerMemRef", "lower-memref", "bool", /*default=*/"false",
+ "Also convert memref dialect operations.">
];
}
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 3d1e7602537098..aab69a619d4cfe 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -5279,8 +5279,9 @@ class FIRToLLVMLowering
mlir::index::populateIndexToLLVMConversionPatterns(typeConverter, pattern);
mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern);
mlir::ub::populateUBToLLVMConversionPatterns(typeConverter, pattern);
- mlir::populateFinalizeMemRefToLLVMConversionPatterns(typeConverter, pattern,
- &symbolTables);
+ if (lowerMemRef)
+ mlir::populateFinalizeMemRefToLLVMConversionPatterns(
+ typeConverter, pattern, &symbolTables);
// Flang specific overloads for OpenMP operations, to allow for special
// handling of things like Box types.
diff --git a/flang/test/Fir/memref-ops-codegen.mlir b/flang/test/Fir/memref-ops-codegen.mlir
index cd2367143ea7f2..e4d803a8df3b02 100644
--- a/flang/test/Fir/memref-ops-codegen.mlir
+++ b/flang/test/Fir/memref-ops-codegen.mlir
@@ -1,8 +1,11 @@
-// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" --split-input-file %s | FileCheck %s
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu lower-memref=true" --split-input-file %s | FileCheck %s
+// RUN: not fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" --split-input-file %s 2>&1 | FileCheck %s --check-prefix=DISABLED
// Test that memref dialect operations, as produced by fir-to-memref and
// lower-affine, are lowered together with the fir.convert ops that bridge
-// !fir.ref and memref values.
+// !fir.ref and memref values when lower-memref is enabled.
+
+// DISABLED: failed to legalize operation 'memref.load'
// CHECK-LABEL: llvm.func @load_scalar(
// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr) -> i32 {
More information about the flang-commits
mailing list