1 | //===- AliasAnalysis.cpp - Alias Analysis for MLIR ------------------------===// |
---|---|
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 | #include "mlir/Analysis/AliasAnalysis.h" |
10 | #include "mlir/Analysis/AliasAnalysis/LocalAliasAnalysis.h" |
11 | #include "mlir/IR/Operation.h" |
12 | #include "mlir/IR/Value.h" |
13 | #include "mlir/Support/LLVM.h" |
14 | #include <memory> |
15 | |
16 | using namespace mlir; |
17 | |
18 | //===----------------------------------------------------------------------===// |
19 | // AliasResult |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | /// Merge this alias result with `other` and return a new result that |
23 | /// represents the conservative merge of both results. |
24 | AliasResult AliasResult::merge(AliasResult other) const { |
25 | if (kind == other.kind) |
26 | return *this; |
27 | // A mix of PartialAlias and MustAlias is PartialAlias. |
28 | if ((isPartial() && other.isMust()) || (other.isPartial() && isMust())) |
29 | return PartialAlias; |
30 | // Otherwise, don't assume anything. |
31 | return MayAlias; |
32 | } |
33 | |
34 | void AliasResult::print(raw_ostream &os) const { |
35 | switch (kind) { |
36 | case Kind::NoAlias: |
37 | os << "NoAlias"; |
38 | break; |
39 | case Kind::MayAlias: |
40 | os << "MayAlias"; |
41 | break; |
42 | case Kind::PartialAlias: |
43 | os << "PartialAlias"; |
44 | break; |
45 | case Kind::MustAlias: |
46 | os << "MustAlias"; |
47 | break; |
48 | } |
49 | } |
50 | |
51 | //===----------------------------------------------------------------------===// |
52 | // ModRefResult |
53 | //===----------------------------------------------------------------------===// |
54 | |
55 | void ModRefResult::print(raw_ostream &os) const { |
56 | switch (kind) { |
57 | case Kind::NoModRef: |
58 | os << "NoModRef"; |
59 | break; |
60 | case Kind::Ref: |
61 | os << "Ref"; |
62 | break; |
63 | case Kind::Mod: |
64 | os << "Mod"; |
65 | break; |
66 | case Kind::ModRef: |
67 | os << "ModRef"; |
68 | break; |
69 | } |
70 | } |
71 | |
72 | //===----------------------------------------------------------------------===// |
73 | // AliasAnalysis |
74 | //===----------------------------------------------------------------------===// |
75 | |
76 | AliasAnalysis::AliasAnalysis(Operation *op) { |
77 | addAnalysisImplementation(analysis: LocalAliasAnalysis()); |
78 | } |
79 | |
80 | AliasResult AliasAnalysis::alias(Value lhs, Value rhs) { |
81 | // Check each of the alias analysis implemenations for an alias result. |
82 | for (const std::unique_ptr<Concept> &aliasImpl : aliasImpls) { |
83 | AliasResult result = aliasImpl->alias(lhs, rhs); |
84 | if (!result.isMay()) |
85 | return result; |
86 | } |
87 | return AliasResult::MayAlias; |
88 | } |
89 | |
90 | ModRefResult AliasAnalysis::getModRef(Operation *op, Value location) { |
91 | // Compute the mod-ref behavior by refining a top `ModRef` result with each of |
92 | // the alias analysis implementations. We early exit at the point where we |
93 | // refine down to a `NoModRef`. |
94 | ModRefResult result = ModRefResult::getModAndRef(); |
95 | for (const std::unique_ptr<Concept> &aliasImpl : aliasImpls) { |
96 | result = result.intersect(other: aliasImpl->getModRef(op, location)); |
97 | if (result.isNoModRef()) |
98 | return result; |
99 | } |
100 | return result; |
101 | } |
102 |