[flang-commits] [flang] [flang][test] Experimental support of MemoryEffectOpInterface for fir.call. (PR #191580)
via flang-commits
flang-commits at lists.llvm.org
Fri Apr 10 17:27:04 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Slava Zakharin (vzakhari)
<details>
<summary>Changes</summary>
I would like to experiment with `fir.call` implementing
`MemoryEffectOpInterface`. So the main change is the fall-through
path in FIR AA. It should be NFC for Flang.
---
Full diff: https://github.com/llvm/llvm-project/pull/191580.diff
3 Files Affected:
- (modified) flang/lib/Optimizer/Analysis/AliasAnalysis.cpp (+7-2)
- (added) flang/test/Analysis/AliasAnalysis/modref-call-memory-effects.fir (+28)
- (modified) flang/test/lib/Analysis/AliasAnalysis/TestAliasAnalysis.cpp (+49)
``````````diff
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 8b8cb9c658e4a..c49928e3bad06 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -732,8 +732,13 @@ ModRefResult AliasAnalysis::getCallModRef(Operation *op, Value var) {
/// 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);
+ if (auto call = llvm::dyn_cast<fir::CallOp>(op)) {
+ ModRefResult result = getCallModRef(call, location);
+ if (result != ModRefResult::getModAndRef())
+ return result;
+ // Proceed to MemoryEffectOpInterface analysis in case one
+ // is attached for fir.call.
+ }
// Build a ModRefResult by merging the behavior of the effects of this
// operation.
diff --git a/flang/test/Analysis/AliasAnalysis/modref-call-memory-effects.fir b/flang/test/Analysis/AliasAnalysis/modref-call-memory-effects.fir
new file mode 100644
index 0000000000000..71f4929255497
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/modref-call-memory-effects.fir
@@ -0,0 +1,28 @@
+// RUN: fir-opt -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis-modref-call-effects))' \
+// RUN: --mlir-disable-threading %s -o /dev/null 2>&1 | FileCheck %s
+
+// Test that when MemoryEffectOpInterface is externally attached to fir.call,
+// fir::AliasAnalysis::getModRef uses it to refine the result after
+// getCallModRef returns ModAndRef.
+
+// The test infrastructure attaches MemoryEffectOpInterface to fir::CallOp
+// such that calls to functions starting with "test_pure" have no memory
+// effects, while all other calls read and write DefaultResource.
+
+// "test_pure_call" has no memory effects via the attached interface,
+// so it cannot modify or reference the variable.
+// "test_impure_call" reads and writes DefaultResource without specifying
+// a value, so alias analysis conservatively reports ModRef.
+
+func.func @test_call_effects(%arg0: !fir.ref<f32>) {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg0 dummy_scope %0 arg 1 {test.ptr = "x", uniq_name = "_QFtestEx"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32>
+ fir.call @test_pure_call() {test.ptr = "pure_call"} : () -> ()
+ fir.call @test_impure_call() {test.ptr = "impure_call"} : () -> ()
+ return
+}
+func.func private @test_pure_call()
+func.func private @test_impure_call()
+// CHECK-LABEL: Testing : "test_call_effects"
+// CHECK-DAG: pure_call -> x#0: NoModRef
+// CHECK-DAG: impure_call -> x#0: ModRef
diff --git a/flang/test/lib/Analysis/AliasAnalysis/TestAliasAnalysis.cpp b/flang/test/lib/Analysis/AliasAnalysis/TestAliasAnalysis.cpp
index 39aaf8fba180a..19f9ffaa50030 100644
--- a/flang/test/lib/Analysis/AliasAnalysis/TestAliasAnalysis.cpp
+++ b/flang/test/lib/Analysis/AliasAnalysis/TestAliasAnalysis.cpp
@@ -8,8 +8,10 @@
#include "mlir/test/lib/Analysis/TestAliasAnalysis.h"
#include "mlir/Analysis/AliasAnalysis.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Pass/Pass.h"
#include "flang/Optimizer/Analysis/AliasAnalysis.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
using namespace mlir;
@@ -56,6 +58,52 @@ struct TestFIRAliasAnalysisModRefPass
runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
}
};
+//===----------------------------------------------------------------------===//
+// Testing ModRefResult with MemoryEffectOpInterface attached to fir.call
+//===----------------------------------------------------------------------===//
+
+/// External model that attaches MemoryEffectOpInterface to fir::CallOp.
+/// Calls to functions whose name starts with "test_pure" have no memory
+/// effects; all other calls read and write DefaultResource.
+struct TestCallMemoryEffectsModel
+ : public MemoryEffectOpInterface::ExternalModel<TestCallMemoryEffectsModel,
+ fir::CallOp> {
+ void getEffects(Operation *op,
+ llvm::SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+ &effects) const {
+ auto call = cast<fir::CallOp>(op);
+ if (auto callee = call.getCallee())
+ if (callee->getLeafReference().getValue().starts_with("test_pure"))
+ return;
+ effects.emplace_back(
+ MemoryEffects::Read::get(), SideEffects::DefaultResource::get());
+ effects.emplace_back(
+ MemoryEffects::Write::get(), SideEffects::DefaultResource::get());
+ }
+};
+
+struct TestFIRAliasAnalysisModRefCallEffectsPass
+ : public test::TestAliasAnalysisModRefBase,
+ PassWrapper<TestFIRAliasAnalysisModRefCallEffectsPass, OperationPass<>> {
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(
+ TestFIRAliasAnalysisModRefCallEffectsPass)
+
+ StringRef getArgument() const final {
+ return "test-fir-alias-analysis-modref-call-effects";
+ }
+ StringRef getDescription() const final {
+ return "Test alias analysis ModRef results with MemoryEffectOpInterface "
+ "attached to fir.call.";
+ }
+ void runOnOperation() override {
+ MLIRContext *ctx = &getContext();
+ fir::CallOp::attachInterface<TestCallMemoryEffectsModel>(*ctx);
+
+ AliasAnalysis aliasAnalysis(getOperation());
+ aliasAnalysis.addAnalysisImplementation(fir::AliasAnalysis());
+ runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
+ }
+};
} // namespace
//===----------------------------------------------------------------------===//
@@ -67,6 +115,7 @@ namespace test {
void registerTestFIRAliasAnalysisPass() {
PassRegistration<TestFIRAliasAnalysisPass>();
PassRegistration<TestFIRAliasAnalysisModRefPass>();
+ PassRegistration<TestFIRAliasAnalysisModRefCallEffectsPass>();
}
} // namespace test
} // namespace fir
\ No newline at end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/191580
More information about the flang-commits
mailing list