xref: /llvm-project/mlir/lib/Analysis/AliasAnalysis.cpp (revision a723a5b637f3a5b0993d5441f36c42221b3777db)
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.
merge(AliasResult other) const24 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 
print(raw_ostream & os) const34 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 
print(raw_ostream & os) const55 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 
AliasAnalysis(Operation * op)76 AliasAnalysis::AliasAnalysis(Operation *op) {
77   addAnalysisImplementation(LocalAliasAnalysis());
78 }
79 
alias(Value lhs,Value rhs)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 
getModRef(Operation * op,Value location)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(aliasImpl->getModRef(op, location));
97     if (result.isNoModRef())
98       return result;
99   }
100   return result;
101 }
102