[flang-commits] [flang] [flang] Let FIR AA:getModRef recognize Fortran user procedures late. (PR #181295)

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Thu Feb 12 19:11:31 PST 2026


https://github.com/vzakhari created https://github.com/llvm/llvm-project/pull/181295

In order to use FIR AA::getModRef() after `ExternalNameConversion`
pass we have to teach it to recognize Fortran user procedures
that have already been renamed.


>From f45c8eee46f2f18c506afa11e34e3e50ea93a6b3 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Thu, 12 Feb 2026 18:01:37 -0800
Subject: [PATCH] [flang] Let FIR AA:getModRef recognize Fortran user
 procedures late.

In order to use FIR AA::getModRef() after `ExternalNameConversion`
pass we have to teach it to recognize Fortran user procedures
that have already been renamed.
---
 .../flang/Optimizer/Analysis/AliasAnalysis.h  |  9 ++++++
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  | 32 ++++++++++++++++---
 ...ef-call-after-external-name-conversion.fir | 16 ++++++++++
 3 files changed, 52 insertions(+), 5 deletions(-)
 create mode 100644 flang/test/Analysis/AliasAnalysis/modref-call-after-external-name-conversion.fir

diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index b896532976332..9c2a11daa22a3 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -248,6 +248,15 @@ struct AliasAnalysis {
   bool symbolMayHaveTargetAttr(mlir::SymbolRefAttr symbol,
                                mlir::Operation *from);
 
+  /// Return true if the given operation is a call to a Fortran user
+  /// procedure.
+  bool isCallToFortranUserProcedure(mlir::Operation *op);
+
+  /// Returns the modify-reference behavior of the given call
+  /// operation `op` on `var`. If `op` is not a fir.call, then
+  /// it returns the conservative ModAndRef result.
+  mlir::ModRefResult getCallModRef(mlir::Operation *op, mlir::Value var);
+
   /// A map between operations with OpTrait::SymbolTable
   /// and the SymbolTable objects associated with them.
   /// TODO: it might be better to initialize just a single SymbolTable
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 0eb00e2f0c549..1dd64d39ee884 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -495,18 +495,40 @@ static bool isSavedLocal(const fir::AliasAnalysis::Source &src) {
   return false;
 }
 
-static bool isCallToFortranUserProcedure(fir::CallOp call) {
+bool AliasAnalysis::isCallToFortranUserProcedure(Operation *op) {
+  fir::CallOp call = dyn_cast<fir::CallOp>(op);
+  if (!call)
+    return false;
+
   // TODO: indirect calls are excluded by these checks. Maybe some attribute is
   // needed to flag user calls in this case.
   if (fir::hasBindcAttr(call))
     return true;
-  if (std::optional<mlir::SymbolRefAttr> callee = call.getCallee())
-    return fir::NameUniquer::deconstruct(callee->getLeafReference().getValue())
-               .first == fir::NameUniquer::NameKind::PROCEDURE;
+  if (std::optional<SymbolRefAttr> callee = call.getCallee()) {
+    if (fir::NameUniquer::deconstruct(callee->getLeafReference().getValue())
+            .first == fir::NameUniquer::NameKind::PROCEDURE)
+      return true;
+
+    const SymbolTable *symTab = getNearestSymbolTable(call);
+    if (!symTab)
+      return false;
+
+    if (auto funcOp =
+            symTab->lookup<FunctionOpInterface>(callee->getLeafReference()))
+      if (auto name = funcOp->getAttrOfType<StringAttr>(
+              fir::getInternalFuncNameAttrName()))
+        if (fir::NameUniquer::deconstruct(name.getValue()).first ==
+            fir::NameUniquer::NameKind::PROCEDURE)
+          return true;
+  }
   return false;
 }
 
-static ModRefResult getCallModRef(fir::CallOp call, mlir::Value var) {
+ModRefResult AliasAnalysis::getCallModRef(Operation *op, Value var) {
+  auto call = dyn_cast<fir::CallOp>(op);
+  if (!call)
+    return ModRefResult::getModAndRef();
+
   // TODO: limit to Fortran functions??
   // 1. Detect variables that can be accessed indirectly.
   fir::AliasAnalysis aliasAnalysis;
diff --git a/flang/test/Analysis/AliasAnalysis/modref-call-after-external-name-conversion.fir b/flang/test/Analysis/AliasAnalysis/modref-call-after-external-name-conversion.fir
new file mode 100644
index 0000000000000..f31ac95b29547
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/modref-call-after-external-name-conversion.fir
@@ -0,0 +1,16 @@
+// 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
+
+// Test that fir.call modref can recognize Fortran user procedures
+// after ExternalNameConversion pass.
+
+// CHECK-LABEL: Testing : "test_modref_"
+// CHECK: callee_procedure -> xx#0: NoModRef
+func.func @test_modref_() {
+  %0 = fir.dummy_scope : !fir.dscope
+  %1 = fir.alloca f32 {bindc_name = "xx", uniq_name = "_QFtest_modrefExx"}
+  %2 = fir.declare %1 {test.ptr = "xx", uniq_name = "_QFtest_modrefExx"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  fir.call @callee_() {test.ptr = "callee_procedure"} : () -> ()
+  return
+}
+func.func private @callee_() attributes {fir.internal_name = "_QPcallee"}



More information about the flang-commits mailing list