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 
14b9c876bdSRiver Riddle #include "mlir/Analysis/AliasAnalysis.h"
15b9c876bdSRiver Riddle #include "mlir/Pass/Pass.h"
16b9c876bdSRiver Riddle 
17b9c876bdSRiver Riddle using namespace mlir;
18b9c876bdSRiver Riddle 
19d47dd110SRiver Riddle /// Print a value that is used as an operand of an alias query.
printAliasOperand(Operation * op)20d47dd110SRiver Riddle static void printAliasOperand(Operation *op) {
21d47dd110SRiver Riddle   llvm::errs() << op->getAttrOfType<StringAttr>("test.ptr").getValue();
22d47dd110SRiver Riddle }
printAliasOperand(Value value)23d47dd110SRiver Riddle static void printAliasOperand(Value value) {
24d47dd110SRiver Riddle   if (BlockArgument arg = value.dyn_cast<BlockArgument>()) {
25d47dd110SRiver Riddle     Region *region = arg.getParentRegion();
26d47dd110SRiver Riddle     unsigned parentBlockNumber =
27d47dd110SRiver Riddle         std::distance(region->begin(), arg.getOwner()->getIterator());
28d47dd110SRiver Riddle     llvm::errs() << region->getParentOp()
29d47dd110SRiver Riddle                         ->getAttrOfType<StringAttr>("test.ptr")
30d47dd110SRiver Riddle                         .getValue()
31d47dd110SRiver Riddle                  << ".region" << region->getRegionNumber();
32d47dd110SRiver Riddle     if (parentBlockNumber != 0)
33d47dd110SRiver Riddle       llvm::errs() << ".block" << parentBlockNumber;
34d47dd110SRiver Riddle     llvm::errs() << "#" << arg.getArgNumber();
35d47dd110SRiver Riddle     return;
36d47dd110SRiver Riddle   }
37d47dd110SRiver Riddle   OpResult result = value.cast<OpResult>();
38d47dd110SRiver Riddle   printAliasOperand(result.getOwner());
39d47dd110SRiver Riddle   llvm::errs() << "#" << result.getResultNumber();
40d47dd110SRiver Riddle }
41d47dd110SRiver Riddle 
42d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
43d47dd110SRiver Riddle // Testing AliasResult
44d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
45d47dd110SRiver Riddle 
46b9c876bdSRiver Riddle namespace {
47b9c876bdSRiver Riddle struct TestAliasAnalysisPass
48b9c876bdSRiver Riddle     : public PassWrapper<TestAliasAnalysisPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon2eb398a90111::TestAliasAnalysisPass49*5e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisPass)
50*5e50dd04SRiver Riddle 
51b5e22e6dSMehdi Amini   StringRef getArgument() const final { return "test-alias-analysis"; }
getDescription__anon2eb398a90111::TestAliasAnalysisPass52b5e22e6dSMehdi Amini   StringRef getDescription() const final {
53b5e22e6dSMehdi Amini     return "Test alias analysis results.";
54b5e22e6dSMehdi Amini   }
runOnOperation__anon2eb398a90111::TestAliasAnalysisPass55b9c876bdSRiver Riddle   void runOnOperation() override {
56d47dd110SRiver Riddle     llvm::errs() << "Testing : " << getOperation()->getAttr("sym_name") << "\n";
57b9c876bdSRiver Riddle 
58b9c876bdSRiver Riddle     // Collect all of the values to check for aliasing behavior.
59b9c876bdSRiver Riddle     AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
60b9c876bdSRiver Riddle     SmallVector<Value, 32> valsToCheck;
61b9c876bdSRiver Riddle     getOperation()->walk([&](Operation *op) {
62b9c876bdSRiver Riddle       if (!op->getAttr("test.ptr"))
63b9c876bdSRiver Riddle         return;
64b9c876bdSRiver Riddle       valsToCheck.append(op->result_begin(), op->result_end());
65b9c876bdSRiver Riddle       for (Region &region : op->getRegions())
66b9c876bdSRiver Riddle         for (Block &block : region)
67b9c876bdSRiver Riddle           valsToCheck.append(block.args_begin(), block.args_end());
68b9c876bdSRiver Riddle     });
69b9c876bdSRiver Riddle 
70b9c876bdSRiver Riddle     // Check for aliasing behavior between each of the values.
71b9c876bdSRiver Riddle     for (auto it = valsToCheck.begin(), e = valsToCheck.end(); it != e; ++it)
7202b6fb21SMehdi Amini       for (auto *innerIt = valsToCheck.begin(); innerIt != it; ++innerIt)
73b9c876bdSRiver Riddle         printAliasResult(aliasAnalysis.alias(*innerIt, *it), *innerIt, *it);
74b9c876bdSRiver Riddle   }
75b9c876bdSRiver Riddle 
76b9c876bdSRiver Riddle   /// Print the result of an alias query.
printAliasResult__anon2eb398a90111::TestAliasAnalysisPass77b9c876bdSRiver Riddle   void printAliasResult(AliasResult result, Value lhs, Value rhs) {
78b9c876bdSRiver Riddle     printAliasOperand(lhs);
79b9c876bdSRiver Riddle     llvm::errs() << " <-> ";
80b9c876bdSRiver Riddle     printAliasOperand(rhs);
81d47dd110SRiver Riddle     llvm::errs() << ": " << result << "\n";
82b9c876bdSRiver Riddle   }
83b9c876bdSRiver Riddle };
84be0a7e9fSMehdi Amini } // namespace
85b9c876bdSRiver Riddle 
86d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
87d47dd110SRiver Riddle // Testing ModRefResult
88d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
89d47dd110SRiver Riddle 
90d47dd110SRiver Riddle namespace {
91d47dd110SRiver Riddle struct TestAliasAnalysisModRefPass
92d47dd110SRiver Riddle     : public PassWrapper<TestAliasAnalysisModRefPass, OperationPass<>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon2eb398a90311::TestAliasAnalysisModRefPass93*5e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestAliasAnalysisModRefPass)
94*5e50dd04SRiver Riddle 
95b5e22e6dSMehdi Amini   StringRef getArgument() const final { return "test-alias-analysis-modref"; }
getDescription__anon2eb398a90311::TestAliasAnalysisModRefPass96b5e22e6dSMehdi Amini   StringRef getDescription() const final {
97b5e22e6dSMehdi Amini     return "Test alias analysis ModRef results.";
98b5e22e6dSMehdi Amini   }
runOnOperation__anon2eb398a90311::TestAliasAnalysisModRefPass99d47dd110SRiver Riddle   void runOnOperation() override {
100d47dd110SRiver Riddle     llvm::errs() << "Testing : " << getOperation()->getAttr("sym_name") << "\n";
101d47dd110SRiver Riddle 
102d47dd110SRiver Riddle     // Collect all of the values to check for aliasing behavior.
103d47dd110SRiver Riddle     AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
104d47dd110SRiver Riddle     SmallVector<Value, 32> valsToCheck;
105d47dd110SRiver Riddle     getOperation()->walk([&](Operation *op) {
106d47dd110SRiver Riddle       if (!op->getAttr("test.ptr"))
107d47dd110SRiver Riddle         return;
108d47dd110SRiver Riddle       valsToCheck.append(op->result_begin(), op->result_end());
109d47dd110SRiver Riddle       for (Region &region : op->getRegions())
110d47dd110SRiver Riddle         for (Block &block : region)
111d47dd110SRiver Riddle           valsToCheck.append(block.args_begin(), block.args_end());
112d47dd110SRiver Riddle     });
113d47dd110SRiver Riddle 
114d47dd110SRiver Riddle     // Check for aliasing behavior between each of the values.
115e5639b3fSMehdi Amini     for (auto &it : valsToCheck) {
116d47dd110SRiver Riddle       getOperation()->walk([&](Operation *op) {
117d47dd110SRiver Riddle         if (!op->getAttr("test.ptr"))
118d47dd110SRiver Riddle           return;
119e5639b3fSMehdi Amini         printModRefResult(aliasAnalysis.getModRef(op, it), op, it);
120d47dd110SRiver Riddle       });
121d47dd110SRiver Riddle     }
122d47dd110SRiver Riddle   }
123d47dd110SRiver Riddle 
124d47dd110SRiver Riddle   /// Print the result of an alias query.
printModRefResult__anon2eb398a90311::TestAliasAnalysisModRefPass125d47dd110SRiver Riddle   void printModRefResult(ModRefResult result, Operation *op, Value location) {
126d47dd110SRiver Riddle     printAliasOperand(op);
127d47dd110SRiver Riddle     llvm::errs() << " -> ";
128d47dd110SRiver Riddle     printAliasOperand(location);
129d47dd110SRiver Riddle     llvm::errs() << ": " << result << "\n";
130d47dd110SRiver Riddle   }
131d47dd110SRiver Riddle };
132be0a7e9fSMehdi Amini } // namespace
133d47dd110SRiver Riddle 
134d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
135d47dd110SRiver Riddle // Pass Registration
136d47dd110SRiver Riddle //===----------------------------------------------------------------------===//
137d47dd110SRiver Riddle 
138b9c876bdSRiver Riddle namespace mlir {
139b9c876bdSRiver Riddle namespace test {
registerTestAliasAnalysisPass()140b9c876bdSRiver Riddle void registerTestAliasAnalysisPass() {
141b5e22e6dSMehdi Amini   PassRegistration<TestAliasAnalysisPass>();
142b5e22e6dSMehdi Amini   PassRegistration<TestAliasAnalysisModRefPass>();
143b9c876bdSRiver Riddle }
144b9c876bdSRiver Riddle } // namespace test
145b9c876bdSRiver Riddle } // namespace mlir
146