Skip to content

Commit ba65584

Browse files
committed
Alias Analysis infra in Flang
Differential revision: https://reviews.llvm.org/D136889
1 parent 3698994 commit ba65584

File tree

17 files changed

+375
-57
lines changed

17 files changed

+375
-57
lines changed

flang/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,9 @@ endif()
411411
include(CMakeParseArguments)
412412
include(AddFlang)
413413

414+
if (FLANG_INCLUDE_TESTS)
415+
add_compile_definitions(FLANG_INCLUDE_TESTS=1)
416+
endif()
414417

415418
add_subdirectory(include)
416419
add_subdirectory(lib)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===- AliasAnalysis.h - Alias Analysis in FIR -----------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef FIR_ANALYSIS_ALIASANALYSIS_H_
10+
#define FIR_ANALYSIS_ALIASANALYSIS_H_
11+
12+
#include "mlir/Analysis/AliasAnalysis.h"
13+
14+
namespace fir {
15+
16+
//===----------------------------------------------------------------------===//
17+
// AliasAnalysis
18+
//===----------------------------------------------------------------------===//
19+
class AliasAnalysis {
20+
public:
21+
/// Given two values, return their aliasing behavior.
22+
mlir::AliasResult alias(mlir::Value lhs, mlir::Value rhs);
23+
24+
/// Return the modify-reference behavior of `op` on `location`.
25+
mlir::ModRefResult getModRef(mlir::Operation *op, mlir::Value location);
26+
};
27+
} // namespace fir
28+
29+
#endif // FIR_ANALYSIS_ALIASANALYSIS_H_

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5004,7 +5004,7 @@ Fortran::lower::getIntrinsicArgumentLowering(llvm::StringRef specificName) {
50045004
/// intrinsic function.
50055005
Fortran::lower::ArgLoweringRule Fortran::lower::lowerIntrinsicArgumentAs(
50065006
const IntrinsicArgumentLoweringRules &rules, unsigned position) {
5007-
assert(position < sizeof(rules.args) / sizeof(decltype(*rules.args)) &&
5007+
assert(position < sizeof(rules.args) / (sizeof(decltype(*rules.args))) &&
50085008
"invalid argument");
50095009
return {rules.args[position].lowerAs,
50105010
rules.args[position].handleDynamicOptional};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===- AliasAnalysis.cpp - Alias Analysis for FIR ------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "flang/Optimizer/Analysis/AliasAnalysis.h"
10+
#include "mlir/Interfaces/SideEffectInterfaces.h"
11+
12+
using namespace mlir;
13+
14+
//===----------------------------------------------------------------------===//
15+
// AliasAnalysis: alias
16+
//===----------------------------------------------------------------------===//
17+
18+
namespace fir {
19+
AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
20+
// This is for now a mock analysis
21+
if (lhs == rhs) {
22+
return AliasResult::MustAlias;
23+
}
24+
return AliasResult::MayAlias;
25+
}
26+
27+
//===----------------------------------------------------------------------===//
28+
// AliasAnalysis: getModRef
29+
//===----------------------------------------------------------------------===//
30+
31+
/// This is mostly inspired by MLIR::LocalAliasAnalysis with 2 notable
32+
/// differences 1) Regions are not handled here but will be handled by a data
33+
/// flow analysis to come 2) Allocate and Free effects are considered modifying
34+
ModRefResult AliasAnalysis::getModRef(Operation *op, Value location) {
35+
MemoryEffectOpInterface interface = dyn_cast<MemoryEffectOpInterface>(op);
36+
if (!interface)
37+
return ModRefResult::getModAndRef();
38+
39+
// Build a ModRefResult by merging the behavior of the effects of this
40+
// operation.
41+
SmallVector<MemoryEffects::EffectInstance> effects;
42+
interface.getEffects(effects);
43+
44+
ModRefResult result = ModRefResult::getNoModRef();
45+
for (const MemoryEffects::EffectInstance &effect : effects) {
46+
47+
// Check for an alias between the effect and our memory location.
48+
AliasResult aliasResult = AliasResult::MayAlias;
49+
if (Value effectValue = effect.getValue())
50+
aliasResult = alias(effectValue, location);
51+
52+
// If we don't alias, ignore this effect.
53+
if (aliasResult.isNo())
54+
continue;
55+
56+
// Merge in the corresponding mod or ref for this effect.
57+
if (isa<MemoryEffects::Read>(effect.getEffect())) {
58+
result = result.merge(ModRefResult::getRef());
59+
} else {
60+
result = result.merge(ModRefResult::getMod());
61+
}
62+
if (result.isModAndRef())
63+
break;
64+
}
65+
return result;
66+
}
67+
} // namespace fir
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
add_flang_library(FIRAnalysis
2+
AliasAnalysis.cpp
3+
4+
DEPENDS
5+
FIRBuilder
6+
FIRDialect
7+
FIRSupport
8+
9+
LINK_LIBS
10+
FIRBuilder
11+
FIRDialect
12+
MLIRFuncDialect
13+
MLIRLLVMDialect
14+
MLIRMathTransforms
15+
FIRSupport
16+
)

flang/lib/Optimizer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ add_subdirectory(Dialect)
44
add_subdirectory(HLFIR)
55
add_subdirectory(Support)
66
add_subdirectory(Transforms)
7+
add_subdirectory(Analysis)

flang/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Test runner infrastructure for Flang. This configures the Flang test trees
22
# for use by Lit, and delegates to LLVM's lit test handlers.
3+
add_subdirectory(lib)
34

45
llvm_canonicalize_cmake_booleans(
56
FLANG_BUILD_EXAMPLES
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Exclude tests from libMLIR.so
2+
add_flang_library(FIRTestAnalysis
3+
TestAliasAnalysis.cpp
4+
5+
DEPENDS
6+
FIRDialect
7+
FIRBuilder
8+
FIRSupport
9+
FIRTransforms
10+
FIRAnalysis
11+
${dialect_libs}
12+
13+
LINK_LIBS
14+
FIRDialect
15+
FIRBuilder
16+
FIRSupport
17+
FIRTransforms
18+
FIRAnalysis
19+
${dialect_libs}
20+
MLIRFuncDialect
21+
MLIRLLVMDialect
22+
MLIRAnalysis
23+
MLIRTestAnalysis
24+
)
25+
26+
target_include_directories(FIRTestAnalysis
27+
PRIVATE
28+
${MLIR_MAIN_SRC_DIR}/..
29+
)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//===- TestAliasAnalysis.cpp - Test FIR lias analysis -----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "mlir/test/lib/Analysis/TestAliasAnalysis.h"
10+
#include "mlir/Analysis/AliasAnalysis.h"
11+
#include "mlir/Pass/Pass.h"
12+
#include "flang/Optimizer/Analysis/AliasAnalysis.h"
13+
14+
using namespace mlir;
15+
16+
namespace {
17+
18+
//===----------------------------------------------------------------------===//
19+
// Testing AliasResult
20+
//===----------------------------------------------------------------------===//
21+
22+
struct TestFIRAliasAnalysisPass
23+
: public test::TestAliasAnalysisBase,
24+
PassWrapper<TestFIRAliasAnalysisPass, OperationPass<>> {
25+
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFIRAliasAnalysisPass)
26+
27+
StringRef getArgument() const final { return "test-fir-alias-analysis"; }
28+
StringRef getDescription() const final {
29+
return "Test alias analysis results.";
30+
}
31+
void runOnOperation() override {
32+
mlir::AliasAnalysis aliasAnalysis(getOperation());
33+
aliasAnalysis.addAnalysisImplementation(fir::AliasAnalysis());
34+
runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
35+
}
36+
};
37+
38+
//===----------------------------------------------------------------------===//
39+
// Testing ModRefResult
40+
//===----------------------------------------------------------------------===//
41+
42+
struct TestFIRAliasAnalysisModRefPass
43+
: public test::TestAliasAnalysisModRefBase,
44+
PassWrapper<TestFIRAliasAnalysisModRefPass, OperationPass<>> {
45+
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestFIRAliasAnalysisModRefPass)
46+
47+
StringRef getArgument() const final {
48+
return "test-fir-alias-analysis-modref";
49+
}
50+
StringRef getDescription() const final {
51+
return "Test alias analysis ModRef results.";
52+
}
53+
void runOnOperation() override {
54+
mlir::AliasAnalysis aliasAnalysis(getOperation());
55+
aliasAnalysis.addAnalysisImplementation(fir::AliasAnalysis());
56+
runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
57+
}
58+
};
59+
} // namespace
60+
61+
//===----------------------------------------------------------------------===//
62+
// Pass Registration
63+
//===----------------------------------------------------------------------===//
64+
65+
namespace fir {
66+
namespace test {
67+
void registerTestFIRAliasAnalysisPass() {
68+
PassRegistration<TestFIRAliasAnalysisPass>();
69+
PassRegistration<TestFIRAliasAnalysisModRefPass>();
70+
}
71+
} // namespace test
72+
} // namespace fir
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' -split-input-file 2>&1 | FileCheck %s
2+
3+
// CHECK-LABEL: Testing : "_QPtest"
4+
// CHECK-DAG: alloca_1#0 <-> address_of#0: MayAlias
5+
func.func @_QPtest(%arg1: !fir.ref<i32>) {
6+
%c1_i32 = arith.constant 1 : i32
7+
%0 = fir.alloca () -> () {test.ptr = "alloca_1"}
8+
%1 = fir.address_of(@_QPf) {test.ptr = "address_of"} : () -> i32
9+
%2 = fir.convert %1 : (() -> i32) -> (() -> ())
10+
%4 = fir.convert %0 : (!fir.ref<() -> ()>) -> !fir.llvm_ptr<() -> ()>
11+
fir.store %2 to %4 : !fir.llvm_ptr<() -> ()>
12+
%6 = fir.load %0 : !fir.ref<() -> ()>
13+
fir.call @_QPs(%6) : (() -> ()) -> ()
14+
return
15+
}
16+
17+
// -----
18+
func.func private @_QPs(%arg0: () -> ())
19+
20+
// -----
21+
func.func private @_QPf() -> i32
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(AliasAnalysis)

flang/test/lib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(Analysis)

flang/test/lib/lit.local.cfg

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
# Excluding .cpp file from the extensions since from this level down they are used for the development
3+
config.suffixes = ['.c', '.f', '.F', '.ff', '.FOR', '.for', '.f77', '.f90', '.F90',
4+
'.ff90', '.f95', '.F95', '.ff95', '.fpp', '.FPP', '.cuf'
5+
'.CUF', '.f18', '.F18', '.f03', '.F03', '.f08', '.F08',
6+
'.ll', '.fir', '.mlir']
7+

flang/tools/fir-opt/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@ add_flang_tool(fir-opt fir-opt.cpp)
22
llvm_update_compile_flags(fir-opt)
33
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
44

5+
if(FLANG_INCLUDE_TESTS)
6+
set(test_libs
7+
FIRTestAnalysis
8+
)
9+
endif()
10+
511
target_link_libraries(fir-opt PRIVATE
612
FIRDialect
713
FIRSupport
814
FIRTransforms
915
FIRCodeGen
1016
HLFIRDialect
17+
FIRAnalysis
18+
${test_libs}
1119
${dialect_libs}
1220

1321
# TODO: these should be transitive dependencies from a target providing

flang/tools/fir-opt/fir-opt.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,19 @@
1717
#include "flang/Optimizer/Transforms/Passes.h"
1818

1919
using namespace mlir;
20+
namespace fir {
21+
namespace test {
22+
void registerTestFIRAliasAnalysisPass();
23+
} // namespace test
24+
} // namespace fir
2025

2126
int main(int argc, char **argv) {
2227
fir::support::registerMLIRPassesForFortranTools();
2328
fir::registerOptCodeGenPasses();
2429
fir::registerOptTransformPasses();
30+
#ifdef FLANG_INCLUDE_TESTS
31+
fir::test::registerTestFIRAliasAnalysisPass();
32+
#endif
2533
DialectRegistry registry;
2634
fir::support::registerDialects(registry);
2735
return failed(MlirOptMain(argc, argv, "FIR modular optimizer driver\n",

0 commit comments

Comments
 (0)