[flang][test] Experimental support of MemoryEffectOpInterface for fir.call. (#191580)
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.
This commit is contained in:
1 parent
cdfd0b60d2
commit
89e736d1df
3 files changed
+84
-2
No files matched your search
@@ -724,8 +724,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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user