1b9c876bdSRiver Riddle //===- TestAliasAnalysis.cpp - Test alias analysis results ----------------===//
2b9c876bdSRiver Riddle //
3b9c876bdSRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b9c876bdSRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
5b9c876bdSRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b9c876bdSRiver Riddle //
7b9c876bdSRiver Riddle //===----------------------------------------------------------------------===//
8b9c876bdSRiver Riddle //
9b9c876bdSRiver Riddle // This file contains test passes for constructing and testing alias analysis
10b9c876bdSRiver Riddle // results.
11b9c876bdSRiver Riddle //
12b9c876bdSRiver Riddle //===----------------------------------------------------------------------===//
13b9c876bdSRiver Riddle
14ba65584dSRenaud-K #include "TestAliasAnalysis.h"
15b9c876bdSRiver Riddle #include "mlir/Analysis/AliasAnalysis.h"
16d42cb024SIvan Butygin #include "mlir/Analysis/AliasAnalysis/LocalAliasAnalysis.h"
1734a35a8bSMartin Erhart #include "mlir/Interfaces/FunctionInterfaces.h"
18b9c876bdSRiver Riddle #include "mlir/Pass/Pass.h"
19b9c876bdSRiver Riddle
20b9c876bdSRiver Riddle using namespace mlir;
21b9c876bdSRiver Riddle
22d47dd110SRiver Riddle /// Print a value that is used as an operand of an alias query.
printAliasOperand(Operation * op)23d47dd110SRiver Riddle static void printAliasOperand(Operation *op) {
24d47dd110SRiver Riddle llvm::errs() << op->getAttrOfType<StringAttr>("test.ptr").getValue();
25d47dd110SRiver Riddle }
printAliasOperand(Value value)26d47dd110SRiver Riddle static void printAliasOperand(Value value) {
275550c821STres Popp if (BlockArgument arg = dyn_cast<BlockArgument>(value)) {
28d47dd110SRiver Riddle Region *region = arg.getParentRegion();
29d47dd110SRiver Riddle unsigned parentBlockNumber =
30d47dd110SRiver Riddle std::distance(region->begin(), arg.getOwner()->getIterator());
31d47dd110SRiver Riddle llvm::errs() << region->getParentOp()
32d47dd110SRiver Riddle ->getAttrOfType<StringAttr>("test.ptr")
33d47dd110SRiver Riddle .getValue()
34d47dd110SRiver Riddle << ".region" << region->getRegionNumber();
35d47dd110SRiver Riddle if (parentBlockNumber != 0)
36d47dd110SRiver Riddle llvm::errs() << ".block" << parentBlockNumber;
37d47dd110SRiver Riddle llvm::errs() << "#" << arg.getArgNumber();
38d47dd110SRiver Riddle return;
39d47dd110SRiver Riddle }
405550c821STres Popp OpResult result = cast<OpResult>(value);
41d47dd110SRiver Riddle printAliasOperand(result.getOwner());
42d47dd110SRiver Riddle llvm::errs() << "#" << result.getResultNumber();
43d47dd110SRiver Riddle }
44d47dd110SRiver Riddle
45ba65584dSRenaud-K namespace mlir {
46ba65584dSRenaud-K namespace test {
printAliasResult(AliasResult result,Value lhs,Value rhs)47ba65584dSRenaud-K void printAliasResult(AliasResult result, Value lhs, Value rhs) {
48ba65584dSRenaud-K printAliasOperand(lhs);
49ba65584dSRenaud-K llvm::errs() << " <-> ";
50ba65584dSRenaud-K printAliasOperand(rhs);
51ba65584dSRenaud-K llvm::errs() << ": " << result << "\n";
52b5e22e6dSMehdi Amini }
53ba65584dSRenaud-K
54ba65584dSRenaud-K /// Print the result of an alias query.
printModRefResult(ModRefResult result,Operation * op,Value location)55ba65584dSRenaud-K void printModRefResult(ModRefResult result, Operation *op, Value location) {
56ba65584dSRenaud-K printAliasOperand(op);
57ba65584dSRenaud-K llvm::errs() << " -> ";
58ba65584dSRenaud-K printAliasOperand(location);
59ba65584dSRenaud-K llvm::errs() << ": " << result << "\n";
60ba65584dSRenaud-K }
61ba65584dSRenaud-K
runAliasAnalysisOnOperation(Operation * op,AliasAnalysis & aliasAnalysis)62ba65584dSRenaud-K void TestAliasAnalysisBase::runAliasAnalysisOnOperation(
63ba65584dSRenaud-K Operation *op, AliasAnalysis &aliasAnalysis) {
64*830b9b07SMehdi Amini llvm::errs() << "Testing : " << *op->getInherentAttr("sym_name") << "\n";
65b9c876bdSRiver Riddle
66b9c876bdSRiver Riddle // Collect all of the values to check for aliasing behavior.
67b9c876bdSRiver Riddle SmallVector<Value, 32> valsToCheck;
68ba65584dSRenaud-K op->walk([&](Operation *op) {
69*830b9b07SMehdi Amini if (!op->getDiscardableAttr("test.ptr"))
70b9c876bdSRiver Riddle return;
71b9c876bdSRiver Riddle valsToCheck.append(op->result_begin(), op->result_end());
72b9c876bdSRiver Riddle for (Region ®ion : op->getRegions())
73b9c876bdSRiver Riddle for (Block &block : region)
74b9c876bdSRiver Riddle valsToCheck.append(block.args_begin(), block.args_end());
75b9c876bdSRiver Riddle });
76b9c876bdSRiver Riddle
77b9c876bdSRiver Riddle // Check for aliasing behavior between each of the values.
78b9c876bdSRiver Riddle for (auto it = valsToCheck.begin(), e = valsToCheck.end(); it != e; ++it)
7902b6fb21SMehdi Amini for (auto *innerIt = valsToCheck.begin(); innerIt != it; ++innerIt)
80b9c876bdSRiver Riddle printAliasResult(aliasAnalysis.alias(*innerIt, *it), *innerIt, *it);
81b9c876bdSRiver Riddle }
82b9c876bdSRiver Riddle
runAliasAnalysisOnOperation(Operation * op,AliasAnalysis & aliasAnalysis)83ba65584dSRenaud-K void TestAliasAnalysisModRefBase::runAliasAnalysisOnOperation(
84ba65584dSRenaud-K Operation *op, AliasAnalysis &aliasAnalysis) {
85*830b9b07SMehdi Amini llvm::errs() << "Testing : " << *op->getInherentAttr("sym_name") << "\n";
86d47dd110SRiver Riddle
87d47dd110SRiver Riddle // Collect all of the values to check for aliasing behavior.
88d47dd110SRiver Riddle SmallVector<Value, 32> valsToCheck;
89ba65584dSRenaud-K op->walk([&](Operation *op) {
90*830b9b07SMehdi Amini if (!op->getDiscardableAttr("test.ptr"))
91d47dd110SRiver Riddle return;
92d47dd110SRiver Riddle valsToCheck.append(op->result_begin(), op->result_end());
93d47dd110SRiver Riddle for (Region ®ion : op->getRegions())
94d47dd110SRiver Riddle for (Block &block : region)
95d47dd110SRiver Riddle valsToCheck.append(block.args_begin(), block.args_end());
96d47dd110SRiver Riddle });
97d47dd110SRiver Riddle
98d47dd110SRiver Riddle // Check for aliasing behavior between each of the values.
99e5639b3fSMehdi Amini for (auto &it : valsToCheck) {
100ba65584dSRenaud-K op->walk([&](Operation *op) {
101*830b9b07SMehdi Amini if (!op->getDiscardableAttr("test.ptr"))
102d47dd110SRiver Riddle return;
103e5639b3fSMehdi Amini printModRefResult(aliasAnalysis.getModRef(op, it), op, it);
104d47dd110SRiver Riddle });
105d47dd110SRiver Riddle }
106d47dd110SRiver Riddle }
107d47dd110SRiver Riddle
108ba65584dSRenaud-K } // namespace test
109ba65584dSRenaud-K } // namespace mlir
110ba65584dSRenaud-K
111ba65584dSRenaud-K //===----------------------------------------------------------------------===//
112ba65584dSRenaud-K // Testing AliasResult
113ba65584dSRenaud-K //===----------------------------------------------------------------------===//
114ba65584dSRenaud-K
115ba65584dSRenaud-K namespace {
116ba65584dSRenaud-K struct TestAliasAnalysisPass
117ba65584dSRenaud-K : public test::TestAliasAnalysisBase,
118ba65584dSRenaud-K PassWrapper<TestAliasAnalysisPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anonabeb314c0411::TestAliasAnalysisPass119ba65584dSRenaud-K MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisPass)
120ba65584dSRenaud-K
121ba65584dSRenaud-K StringRef getArgument() const final { return "test-alias-analysis"; }
getDescription__anonabeb314c0411::TestAliasAnalysisPass122ba65584dSRenaud-K StringRef getDescription() const final {
123ba65584dSRenaud-K return "Test alias analysis results.";
124ba65584dSRenaud-K }
runOnOperation__anonabeb314c0411::TestAliasAnalysisPass125ba65584dSRenaud-K void runOnOperation() override {
126ba65584dSRenaud-K AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
127ba65584dSRenaud-K runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
128ba65584dSRenaud-K }
129ba65584dSRenaud-K };
130ba65584dSRenaud-K } // namespace
131ba65584dSRenaud-K
132ba65584dSRenaud-K //===----------------------------------------------------------------------===//
133ba65584dSRenaud-K // Testing ModRefResult
134ba65584dSRenaud-K //===----------------------------------------------------------------------===//
135ba65584dSRenaud-K
136ba65584dSRenaud-K namespace {
137ba65584dSRenaud-K struct TestAliasAnalysisModRefPass
138ba65584dSRenaud-K : public test::TestAliasAnalysisModRefBase,
139ba65584dSRenaud-K PassWrapper<TestAliasAnalysisModRefPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anonabeb314c0511::TestAliasAnalysisModRefPass140ba65584dSRenaud-K MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisModRefPass)
141ba65584dSRenaud-K
142ba65584dSRenaud-K StringRef getArgument() const final { return "test-alias-analysis-modref"; }
getDescription__anonabeb314c0511::TestAliasAnalysisModRefPass143ba65584dSRenaud-K StringRef getDescription() const final {
144ba65584dSRenaud-K return "Test alias analysis ModRef results.";
145ba65584dSRenaud-K }
runOnOperation__anonabeb314c0511::TestAliasAnalysisModRefPass146ba65584dSRenaud-K void runOnOperation() override {
147ba65584dSRenaud-K AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
148ba65584dSRenaud-K runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
149d47dd110SRiver Riddle }
150d47dd110SRiver Riddle };
151be0a7e9fSMehdi Amini } // namespace
152d47dd110SRiver Riddle
153d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
154d42cb024SIvan Butygin // Testing LocalAliasAnalysis extending
155d42cb024SIvan Butygin //===----------------------------------------------------------------------===//
156d42cb024SIvan Butygin
157d42cb024SIvan Butygin /// Check if value is function argument.
isFuncArg(Value val)158d42cb024SIvan Butygin static bool isFuncArg(Value val) {
1595550c821STres Popp auto blockArg = dyn_cast<BlockArgument>(val);
160d42cb024SIvan Butygin if (!blockArg)
161d42cb024SIvan Butygin return false;
162d42cb024SIvan Butygin
163d42cb024SIvan Butygin return mlir::isa_and_nonnull<FunctionOpInterface>(
164d42cb024SIvan Butygin blockArg.getOwner()->getParentOp());
165d42cb024SIvan Butygin }
166d42cb024SIvan Butygin
167d42cb024SIvan Butygin /// Check if value has "restrict" attribute. Value must be a function argument.
isRestrict(Value val)168d42cb024SIvan Butygin static bool isRestrict(Value val) {
1695550c821STres Popp auto blockArg = cast<BlockArgument>(val);
170d42cb024SIvan Butygin auto func =
171d42cb024SIvan Butygin mlir::cast<FunctionOpInterface>(blockArg.getOwner()->getParentOp());
172d42cb024SIvan Butygin return !!func.getArgAttr(blockArg.getArgNumber(),
173d42cb024SIvan Butygin "local_alias_analysis.restrict");
174d42cb024SIvan Butygin }
175d42cb024SIvan Butygin
176d42cb024SIvan Butygin namespace {
177d42cb024SIvan Butygin /// LocalAliasAnalysis extended to support "restrict" attreibute.
178d42cb024SIvan Butygin class LocalAliasAnalysisRestrict : public LocalAliasAnalysis {
179d42cb024SIvan Butygin protected:
aliasImpl(Value lhs,Value rhs)180d42cb024SIvan Butygin AliasResult aliasImpl(Value lhs, Value rhs) override {
181d42cb024SIvan Butygin if (lhs == rhs)
182d42cb024SIvan Butygin return AliasResult::MustAlias;
183d42cb024SIvan Butygin
184d42cb024SIvan Butygin // Assume no aliasing if both values are function arguments and any of them
185d42cb024SIvan Butygin // have restrict attr.
186d42cb024SIvan Butygin if (isFuncArg(lhs) && isFuncArg(rhs))
187d42cb024SIvan Butygin if (isRestrict(lhs) || isRestrict(rhs))
188d42cb024SIvan Butygin return AliasResult::NoAlias;
189d42cb024SIvan Butygin
190d42cb024SIvan Butygin return LocalAliasAnalysis::aliasImpl(lhs, rhs);
191d42cb024SIvan Butygin }
192d42cb024SIvan Butygin };
193d42cb024SIvan Butygin
194d42cb024SIvan Butygin /// This pass tests adding additional analysis impls to the AliasAnalysis.
195d42cb024SIvan Butygin struct TestAliasAnalysisExtendingPass
196d42cb024SIvan Butygin : public test::TestAliasAnalysisBase,
197d42cb024SIvan Butygin PassWrapper<TestAliasAnalysisExtendingPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anonabeb314c0611::TestAliasAnalysisExtendingPass198d42cb024SIvan Butygin MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisExtendingPass)
199d42cb024SIvan Butygin
200d42cb024SIvan Butygin StringRef getArgument() const final {
201d42cb024SIvan Butygin return "test-alias-analysis-extending";
202d42cb024SIvan Butygin }
getDescription__anonabeb314c0611::TestAliasAnalysisExtendingPass203d42cb024SIvan Butygin StringRef getDescription() const final {
204d42cb024SIvan Butygin return "Test alias analysis extending.";
205d42cb024SIvan Butygin }
runOnOperation__anonabeb314c0611::TestAliasAnalysisExtendingPass206d42cb024SIvan Butygin void runOnOperation() override {
207d42cb024SIvan Butygin AliasAnalysis aliasAnalysis(getOperation());
208d42cb024SIvan Butygin aliasAnalysis.addAnalysisImplementation(LocalAliasAnalysisRestrict());
209d42cb024SIvan Butygin runAliasAnalysisOnOperation(getOperation(), aliasAnalysis);
210d42cb024SIvan Butygin }
211d42cb024SIvan Butygin };
212d42cb024SIvan Butygin } // namespace
213d42cb024SIvan Butygin
214d42cb024SIvan Butygin //===----------------------------------------------------------------------===//
215d47dd110SRiver Riddle // Pass Registration
216d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
217d47dd110SRiver Riddle
218b9c876bdSRiver Riddle namespace mlir {
219b9c876bdSRiver Riddle namespace test {
registerTestAliasAnalysisPass()220b9c876bdSRiver Riddle void registerTestAliasAnalysisPass() {
221d42cb024SIvan Butygin PassRegistration<TestAliasAnalysisExtendingPass>();
222b5e22e6dSMehdi Amini PassRegistration<TestAliasAnalysisModRefPass>();
223d42cb024SIvan Butygin PassRegistration<TestAliasAnalysisPass>();
224b9c876bdSRiver Riddle }
225b9c876bdSRiver Riddle } // namespace test
226b9c876bdSRiver Riddle } // namespace mlir
227