xref: /llvm-project/mlir/test/lib/Analysis/TestAliasAnalysis.cpp (revision 830b9b072d8458ee89c48f00d4de59456c9f467f)
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 &region : 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 &region : 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