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.
20 static void printAliasOperand(Operation *op) {
21   llvm::errs() << op->getAttrOfType<StringAttr>("test.ptr").getValue();
22 }
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<>> {
49   StringRef getArgument() const final { return "test-alias-analysis"; }
50   StringRef getDescription() const final {
51     return "Test alias analysis results.";
52   }
53   void runOnOperation() override {
54     llvm::errs() << "Testing : " << getOperation()->getAttr("sym_name") << "\n";
55 
56     // Collect all of the values to check for aliasing behavior.
57     AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
58     SmallVector<Value, 32> valsToCheck;
59     getOperation()->walk([&](Operation *op) {
60       if (!op->getAttr("test.ptr"))
61         return;
62       valsToCheck.append(op->result_begin(), op->result_end());
63       for (Region &region : op->getRegions())
64         for (Block &block : region)
65           valsToCheck.append(block.args_begin(), block.args_end());
66     });
67 
68     // Check for aliasing behavior between each of the values.
69     for (auto it = valsToCheck.begin(), e = valsToCheck.end(); it != e; ++it)
70       for (auto innerIt = valsToCheck.begin(); innerIt != it; ++innerIt)
71         printAliasResult(aliasAnalysis.alias(*innerIt, *it), *innerIt, *it);
72   }
73 
74   /// Print the result of an alias query.
75   void printAliasResult(AliasResult result, Value lhs, Value rhs) {
76     printAliasOperand(lhs);
77     llvm::errs() << " <-> ";
78     printAliasOperand(rhs);
79     llvm::errs() << ": " << result << "\n";
80   }
81 };
82 } // end anonymous namespace
83 
84 //===----------------------------------------------------------------------===//
85 // Testing ModRefResult
86 //===----------------------------------------------------------------------===//
87 
88 namespace {
89 struct TestAliasAnalysisModRefPass
90     : public PassWrapper<TestAliasAnalysisModRefPass, OperationPass<>> {
91   StringRef getArgument() const final { return "test-alias-analysis-modref"; }
92   StringRef getDescription() const final {
93     return "Test alias analysis ModRef results.";
94   }
95   void runOnOperation() override {
96     llvm::errs() << "Testing : " << getOperation()->getAttr("sym_name") << "\n";
97 
98     // Collect all of the values to check for aliasing behavior.
99     AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>();
100     SmallVector<Value, 32> valsToCheck;
101     getOperation()->walk([&](Operation *op) {
102       if (!op->getAttr("test.ptr"))
103         return;
104       valsToCheck.append(op->result_begin(), op->result_end());
105       for (Region &region : op->getRegions())
106         for (Block &block : region)
107           valsToCheck.append(block.args_begin(), block.args_end());
108     });
109 
110     // Check for aliasing behavior between each of the values.
111     for (auto it = valsToCheck.begin(), e = valsToCheck.end(); it != e; ++it) {
112       getOperation()->walk([&](Operation *op) {
113         if (!op->getAttr("test.ptr"))
114           return;
115         printModRefResult(aliasAnalysis.getModRef(op, *it), op, *it);
116       });
117     }
118   }
119 
120   /// Print the result of an alias query.
121   void printModRefResult(ModRefResult result, Operation *op, Value location) {
122     printAliasOperand(op);
123     llvm::errs() << " -> ";
124     printAliasOperand(location);
125     llvm::errs() << ": " << result << "\n";
126   }
127 };
128 } // end anonymous namespace
129 
130 //===----------------------------------------------------------------------===//
131 // Pass Registration
132 //===----------------------------------------------------------------------===//
133 
134 namespace mlir {
135 namespace test {
136 void registerTestAliasAnalysisPass() {
137   PassRegistration<TestAliasAnalysisPass>();
138   PassRegistration<TestAliasAnalysisModRefPass>();
139 }
140 } // namespace test
141 } // namespace mlir
142