• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMPILER_OPTIMIZER_ANALYSIS_ALIAS_ANALYSIS_H_
17 #define COMPILER_OPTIMIZER_ANALYSIS_ALIAS_ANALYSIS_H_
18 
19 #include <unordered_map>
20 #include "optimizer/ir/graph_visitor.h"
21 #include "optimizer/pass.h"
22 #include "utils/arena_containers.h"
23 #include "utils/hash.h"
24 
25 namespace panda::compiler {
26 class BasicBlock;
27 class Graph;
28 
29 enum AliasType : uint8_t {
30     // Proved that references are not aliases
31     NO_ALIAS,
32     // References may or may not alias each other (cannot be proven statically)
33     MAY_ALIAS,
34     // References are proven aliases
35     MUST_ALIAS
36 };
37 
38 enum PointerType {
39     // Reference to unknown object.
40     // Valid fields: base
41     OBJECT,
42     // Constant from pool
43     // Valid fields: imm
44     POOL_CONSTANT,
45     // Object's field
46     // Valid fields: base, imm, type_ptr
47     OBJECT_FIELD,
48     // Static field of the object
49     // Valid fields: imm, type_ptr
50     STATIC_FIELD,
51     // Array pointer
52     // Valid fields: base, idx
53     ARRAY_ELEMENT
54 };
55 
56 class Pointer {
57 public:
58     Pointer() = default;
Pointer(PointerType type,const Inst * base,const Inst * idx,uint64_t imm,const void * type_ptr)59     Pointer(PointerType type, const Inst *base, const Inst *idx, uint64_t imm, const void *type_ptr)
60         : type_(type), base_(base), idx_(idx), imm_(imm), type_ptr_(type_ptr), volatile_(false)
61     {
62         local_ = false;
63     };
64 
CreateObject(const Inst * base)65     static Pointer CreateObject(const Inst *base)
66     {
67         return Pointer(OBJECT, base, nullptr, 0, nullptr);
68     }
69 
70     static Pointer CreateObjectField(const Inst *base, uint32_t type_id, const void *type_ptr = nullptr)
71     {
72         return Pointer(OBJECT_FIELD, base, nullptr, type_id, type_ptr);
73     }
74 
75     static Pointer CreateArrayElement(const Inst *array, const Inst *idx, uint64_t imm = 0)
76     {
77         return Pointer(ARRAY_ELEMENT, array, idx, imm, nullptr);
78     }
79 
GetType()80     PointerType GetType() const
81     {
82         return type_;
83     }
84 
GetBase()85     const Inst *GetBase() const
86     {
87         return base_;
88     }
89 
GetIdx()90     const Inst *GetIdx() const
91     {
92         return idx_;
93     }
94 
GetImm()95     uint64_t GetImm() const
96     {
97         return imm_;
98     }
99 
GetTypePtr()100     const void *GetTypePtr() const
101     {
102         return type_ptr_;
103     }
104 
IsLocal()105     bool IsLocal() const
106     {
107         return local_;
108     }
109 
SetLocalVolatile(bool local,bool is_volatile)110     void SetLocalVolatile(bool local, bool is_volatile)
111     {
112         local_ = local;
113         volatile_ = is_volatile;
114     }
115 
IsVolatile()116     bool IsVolatile() const
117     {
118         return volatile_;
119     }
120 
121     void Dump(std::ostream *out) const;
122 
HasSameOffset(const Pointer & p)123     bool HasSameOffset(const Pointer &p) const
124     {
125         if (type_ptr_ == nullptr && p.type_ptr_ == nullptr) {
126             return imm_ == p.imm_;
127         }
128         return type_ptr_ == p.type_ptr_;
129     }
130 
131 private:
132     PointerType type_;
133     const Inst *base_;
134     const Inst *idx_;
135     uint64_t imm_;
136     const void *type_ptr_;
137     bool local_;
138     bool volatile_;
139 };
140 
141 struct PointerEqual {
operatorPointerEqual142     bool operator()(Pointer const &p1, Pointer const &p2) const
143     {
144         return p1.GetType() == p2.GetType() && p1.GetBase() == p2.GetBase() && p1.GetIdx() == p2.GetIdx() &&
145                p1.HasSameOffset(p2);
146     }
147 };
148 
149 struct PointerHash {
operatorPointerHash150     uint32_t operator()(Pointer const &p) const
151     {
152         auto inst_hasher = std::hash<const Inst *> {};
153         uint32_t hash = inst_hasher(p.GetBase());
154         hash += inst_hasher(p.GetIdx());
155         if (p.GetTypePtr() == nullptr) {
156             hash += std::hash<uint64_t> {}(p.GetImm());
157         } else {
158             hash += std::hash<const void *> {}(p.GetTypePtr());
159         }
160         return hash;
161     }
162 };
163 
164 // NOLINTNEXTLINE(fuchsia-multiple-inheritance)
165 class AliasAnalysis : public Analysis, public GraphVisitor {
166 public:
167     enum class Trilean {
168         TRUE,
169         UNKNOWN,
170         FALSE,
171     };
172 
173     using PointerPairVector = ArenaVector<std::pair<Pointer, Pointer>>;
174 
175     explicit AliasAnalysis(Graph *graph);
176     NO_MOVE_SEMANTIC(AliasAnalysis);
177     NO_COPY_SEMANTIC(AliasAnalysis);
178     ~AliasAnalysis() override = default;
179 
180     bool RunImpl() override;
181 
GetPassName()182     const char *GetPassName() const override
183     {
184         return "AliasAnalysis";
185     }
186 
187     AliasType CheckInstAlias(Inst *mem1, Inst *mem2) const;
188     void Dump(std::ostream *out) const;
189 
190     /**
191      * Sort IR instructions into two constraint groups:
192      *     Direct: introduce the alias
193      *     Copy: copy one alias to another
194      */
195     const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override;
196 
197     /**
198      * Instructions that introduce aliases.
199      */
200     static void VisitCastAnyTypeValue(GraphVisitor *v, Inst *inst);
201 
AddDirectEdge(const Pointer & p)202     void AddDirectEdge(const Pointer &p)
203     {
204         direct_->push_back({p, p});
205     }
206 
GetClearInputsSet()207     ArenaSet<Inst *> *GetClearInputsSet()
208     {
209         inputs_set_->clear();
210         return inputs_set_;
211     }
212 
213 #include "optimizer/ir/visitor.inc"
214 
215 private:
216     void Init();
217     using PointerSet = ArenaUnorderedSet<Pointer, PointerHash, PointerEqual>;
218     template <class T>
219     using PointerMap = ArenaUnorderedMap<Pointer, T, PointerHash, PointerEqual>;
220 
221     void SolveConstraints();
222 
223     void DumpChains(std::ostream *out) const;
224 
225 private:
226     PointerMap<PointerSet> points_to_;
227 
228     // Local containers:
229     PointerMap<ArenaVector<Pointer>> *chains_ {nullptr};
230     PointerPairVector *direct_ {nullptr};
231     ArenaSet<Inst *> *inputs_set_ {nullptr};
232 };
233 }  // namespace panda::compiler
234 
235 #endif  // COMPILER_OPTIMIZER_ANALYSIS_ALIAS_ANALYSIS_H_
236