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