[Mlir-commits] [flang] [mlir] [flang] Fixed MemAlloc/Free effects handling in FIR ModRef. (PR #177728)

Slava Zakharin llvmlistbot at llvm.org
Mon Jan 26 09:39:20 PST 2026


https://github.com/vzakhari updated https://github.com/llvm/llvm-project/pull/177728

>From d87c86269f0486b835f9228c2f721369174b63db Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Fri, 23 Jan 2026 18:53:34 -0800
Subject: [PATCH 1/2] [flang] Fixed MemAlloc/Free effects handling in FIR
 ModRef.

We should ignore MemAlloc/Free effects as they are not
modifying/reading ones. This is what LocalAliasAnalysis
does. This patch also removes the operation-wide MemFree
effect from `fir.freemem`.
---
 .../include/flang/Optimizer/Dialect/FIROps.td |  2 +-
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  |  3 ++
 .../modref-alloc-free-effects.fir             | 37 +++++++++++++++++++
 3 files changed, 41 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Analysis/AliasAnalysis/modref-alloc-free-effects.fir

diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index a177fc483109e..30f5dcc37b0f3 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -270,7 +270,7 @@ def fir_AllocMemOp : fir_Op<"allocmem", [AttrSizedOperandSegments]> {
   }];
 }
 
-def fir_FreeMemOp : fir_Op<"freemem", [MemoryEffects<[MemFree]>]> {
+def fir_FreeMemOp : fir_Op<"freemem", []> {
   let summary = "free a heap object";
 
   let description = [{
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 388fb60fcda35..7d2845810bac8 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -566,6 +566,9 @@ ModRefResult AliasAnalysis::getModRef(Operation *op, Value location) {
   interface.getEffects(effects);
 
   for (const MemoryEffects::EffectInstance &effect : effects) {
+    // MemAlloc and MemFree are not mod-ref effects.
+    if (isa<MemoryEffects::Allocate, MemoryEffects::Free>(effect.getEffect()))
+      continue;
 
     // Check for an alias between the effect and our memory location.
     AliasResult aliasResult = AliasResult::MayAlias;
diff --git a/flang/test/Analysis/AliasAnalysis/modref-alloc-free-effects.fir b/flang/test/Analysis/AliasAnalysis/modref-alloc-free-effects.fir
new file mode 100644
index 0000000000000..892a9796eaac8
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/modref-alloc-free-effects.fir
@@ -0,0 +1,37 @@
+// RUN:  fir-opt -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis-modref))' \
+// RUN:  --mlir-disable-threading %s -o /dev/null 2>&1 | FileCheck %s
+
+// If LocalAliasAnalysis cannot deduce NoModRef (e.g. due to
+// a store unknown to it), then MemAlloc and and MemFree
+// effects should be ignored in FIR AliasAnalysis.
+// They used to be treated as Mod effect.
+
+// CHECK-LABEL: Testing : "test_alloc_effect"
+// CHECK: test_effect -> test_decl#0: Ref
+func.func @test_alloc_effect(%arg0: !fir.ref<i32>, %arg1: !fir.ref<i32>, %arg2: i1) {
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "arg0", test.ptr = "test_decl"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+  fir.if %arg2 {
+    %2 = fir.load %1 : !fir.ref<i32>
+    // fir.declare has MemAlloc effect on the DebuggingResource:
+    %3 = fir.declare %arg1 dummy_scope %0 arg 2 {uniq_name = "arg1"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+    fir.store %2 to %3 : !fir.ref<i32>
+  } {test.ptr = "test_effect"}
+  return
+}
+
+// CHECK-LABEL: Testing : "test_free_effect"
+// CHECK: test_effect -> test_decl#0: Ref
+func.func @test_free_effect(%arg0: !fir.ref<i32>, %arg1: !fir.heap<i32>, %arg2: i1) {
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.declare %arg0 dummy_scope %0 arg 1 {uniq_name = "arg0", test.ptr = "test_decl"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+  %2 = fir.declare %arg1 dummy_scope %0 arg 2 {uniq_name = "arg1"} : (!fir.heap<i32>, !fir.dscope) -> !fir.heap<i32>
+  fir.if %arg2 {
+    %3 = fir.load %1 : !fir.ref<i32>
+    fir.store %3 to %2 : !fir.heap<i32>
+    // fir.freemem used to report operation-wide MemFree effect,
+    // i.e. without specifying the freed value.
+    fir.freemem %2 : !fir.heap<i32>
+  } {test.ptr = "test_effect"}
+  return
+}

>From 56cdcd1e696555be5a1534c42e0db11b5b3028af Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Mon, 26 Jan 2026 09:38:55 -0800
Subject: [PATCH 2/2] Updated comments.

---
 flang/lib/Optimizer/Analysis/AliasAnalysis.cpp | 6 ++----
 mlir/include/mlir/Analysis/AliasAnalysis.h     | 5 +++++
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 7d2845810bac8..4234a72192f31 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -530,10 +530,8 @@ static ModRefResult getCallModRef(fir::CallOp call, mlir::Value var) {
   return ModRefResult::getNoModRef();
 }
 
-/// This is mostly inspired by MLIR::LocalAliasAnalysis with 2 notable
-/// differences 1) Regions are not handled here but will be handled by a data
-/// flow analysis to come 2) Allocate and Free effects are considered
-/// modifying
+/// This is mostly inspired by MLIR::LocalAliasAnalysis, except that
+/// fir.call's are handled in a special way.
 ModRefResult AliasAnalysis::getModRef(Operation *op, Value location) {
   if (auto call = llvm::dyn_cast<fir::CallOp>(op))
     return getCallModRef(call, location);
diff --git a/mlir/include/mlir/Analysis/AliasAnalysis.h b/mlir/include/mlir/Analysis/AliasAnalysis.h
index 5beae79ad1a03..0fdcf01d9b6a3 100644
--- a/mlir/include/mlir/Analysis/AliasAnalysis.h
+++ b/mlir/include/mlir/Analysis/AliasAnalysis.h
@@ -254,6 +254,11 @@ class AliasAnalysis {
   ///     - This method returns a `ModRefResult` that corresponds to the
   ///       modify-reference behavior of `op` on the given `location`. The
   ///       conservative "I don't know" result of this method should be ModRef.
+  ///       Note that operations that only allocate or/and free memory
+  ///       do not have modify-reference behavior on any location.
+  ///       MLIR transformations should make sure to keep the order
+  ///       of operations correct, i.e. do not move reads/writes
+  ///       across allocate/free for the same memory location.
   template <typename AnalysisT>
   void addAnalysisImplementation(AnalysisT &&analysis) {
     aliasImpls.push_back(



More information about the Mlir-commits mailing list