[flang-commits] [flang] [flang] Add support for fir.absent to AliasAnalysis (PR #195938)

Razvan Lupusoru via flang-commits flang-commits at lists.llvm.org
Tue May 5 14:00:32 PDT 2026


https://github.com/razvanlupusoru created https://github.com/llvm/llvm-project/pull/195938

Each fir.absent is classified like a distinct allocation so it does not alias other real storage, another absent, or a global.

>From 7a146b233800a3ad30d8d81b96d6c12e417be417 Mon Sep 17 00:00:00 2001
From: Razvan Lupusoru <rlupusoru at nvidia.com>
Date: Tue, 5 May 2026 13:59:35 -0700
Subject: [PATCH] [flang] Add support for fir.absent to AliasAnalysis

Each fir.absent is classified like a distinct allocation so it
does not alias other real storage, another absent, or a global.
---
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  |  8 +++
 .../AliasAnalysis/alias-analysis-absent.fir   | 60 +++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 flang/test/Analysis/AliasAnalysis/alias-analysis-absent.fir

diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 2509334b8ec4a..b4b48d19d9a1c 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -869,6 +869,14 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
           defOp = v.getDefiningOp();
           approximateSource = true;
         })
+        .Case([&](fir::AbsentOp op) {
+          // Although fir.absent is not a local allocation, we treat it
+          // similarly so that it can be disambiguated that it doesn't alias any
+          // other values. Two entities coming from separate fir.absent ops
+          // also do not alias each other.
+          type = SourceKind::Allocate;
+          breakFromLoop = true;
+        })
         .Case([&](fir::LoadOp op) {
           // If load is inside target and it points to mapped item,
           // continue tracking.
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-absent.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-absent.fir
new file mode 100644
index 0000000000000..f8c97d48a3594
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-absent.fir
@@ -0,0 +1,60 @@
+// Exercise FIR alias analysis for values rooted at fir.absent.
+// Each fir.absent is classified like a distinct allocation so it
+// does not alias real storage, another absent, or a global; it only
+// aliases itself.
+
+// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' \
+// RUN:   -split-input-file --mlir-disable-threading 2>&1 | FileCheck %s
+
+// CHECK-LABEL: Testing : "_QPtest_absent"
+// CHECK-DAG: absent1#0 <-> absent2#0: NoAlias
+// CHECK-DAG: real#0 <-> absent1#0: NoAlias
+// CHECK-DAG: real#0 <-> absent2#0: NoAlias
+
+func.func @_QPtest_absent() {
+  %c10 = arith.constant 10 : index
+  %shape = fir.shape %c10 : (index) -> !fir.shape<1>
+  %alloc = fir.alloca !fir.array<10xf32>
+  %real = fir.declare %alloc(%shape) {uniq_name = "_QPtest_absentEx", test.ptr = "real"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+  %abs1 = fir.absent !fir.ref<!fir.array<10xf32>> {test.ptr = "absent1"}
+  %abs2 = fir.absent !fir.ref<!fir.array<10xf32>> {test.ptr = "absent2"}
+  return
+}
+
+// -----
+
+// Same fir.absent via fir.convert and fir.declare
+// CHECK-LABEL: Testing : "_QPtest_absent_same_through_convert"
+// CHECK-DAG: abs_slot#0 <-> via_convert#0: MustAlias
+// CHECK-DAG: abs_slot#0 <-> direct_abs#0: MustAlias
+// CHECK-DAG: via_convert#0 <-> direct_abs#0: MustAlias
+
+func.func @_QPtest_absent_same_through_convert() {
+  %c10 = arith.constant 10 : index
+  %shape = fir.shape %c10 : (index) -> !fir.shape<1>
+  %abs = fir.absent !fir.ref<!fir.array<10xf32>> {test.ptr = "abs_slot"}
+  %conv = fir.convert %abs : (!fir.ref<!fir.array<10xf32>>) -> !fir.ref<!fir.array<10xf32>>
+  %via = fir.declare %conv(%shape) {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QPtest_absent_sameEv", test.ptr = "via_convert"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+  %direct = fir.declare %abs(%shape) {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QPtest_absent_sameEd", test.ptr = "direct_abs"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+  return
+}
+
+// -----
+
+// Global array storage must not alias an absent.
+// CHECK-LABEL: Testing : "_QPtest_absent_vs_global"
+// CHECK-DAG: {{(absent_g#0 <-> global#0|global#0 <-> absent_g#0)}}: NoAlias
+
+fir.global @_QPtest_absent_vs_global_g : !fir.array<10xf32> {
+  %0 = fir.undefined !fir.array<10xf32>
+  fir.has_value %0 : !fir.array<10xf32>
+}
+
+func.func @_QPtest_absent_vs_global() {
+  %c10 = arith.constant 10 : index
+  %shape = fir.shape %c10 : (index) -> !fir.shape<1>
+  %gaddr = fir.address_of(@_QPtest_absent_vs_global_g) : !fir.ref<!fir.array<10xf32>>
+  %g = fir.declare %gaddr(%shape) {uniq_name = "_QPtest_absent_vs_globalEg", test.ptr = "global"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+  %abs = fir.absent !fir.ref<!fir.array<10xf32>> {test.ptr = "absent_g"}
+  return
+}



More information about the flang-commits mailing list