[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