• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #include "optimizer/ir/analysis.h"
17 #include "optimizer/ir/basicblock.h"
18 #include "optimizer/ir/graph.h"
19 #include "optimizer/analysis/alias_analysis.h"
20 #include "compiler_logger.h"
21 
22 /**
23  * See  "Efficient Field-sensitive pointer analysis for C" by "David J. Pearce
24  * and Paul H. J. Kelly and Chris Hankin
25  *
26  * We treat each IR Inst as a constraint that may be applied to a set of
27  * aliases of some virtual register.  Virtual registers are used as constraint
28  * variables as well.
29  *
30  * In order to solve the system of set constraints, the following is done:
31  *
32  * 1. Each constraint variable x has a solution set associated with it, Sol(x).
33  * Implemented through AliasAnalysis::points_to_ that contains mapping of
34  * virtual register to possible aliases.
35  *
36  * 2. Constraints are separated into direct, copy.
37  *
38  * - Direct constraints are constraints that require no extra processing, such
39  * as P = &Q.
40  *
41  * - Copy constraints are those of the form P = Q.  Such semantic can be
42  * obtained through NullCheck, Mov, and Phi instructions.
43  *
44  * 3. All direct constraints of the form P = &Q are processed, such that Q is
45  * added to Sol(P).
46  *
47  * 4. A directed graph is built out of the copy constraints.  Each constraint
48  * variable is a node in the graph, and an edge from Q to P is added for each
49  * copy constraint of the form P = Q.
50  *
51  * 5. The graph is then walked, and solution sets are propagated along the copy
52  * edges, such that an edge from Q to P causes Sol(P) <- Sol(P) union Sol(Q).
53  *
54  * 6. The process of walking the graph is iterated until no solution sets
55  * change.
56  *
57  * To add new instructions to alias analysis please consider following:
58  *     - IsLocalAlias method: to add instructions that create new object
59  *     - ParseInstruction method: to add a new instruction alias analysis works for
60  *     - AliasAnalysis class: to add a visitor for a new instruction that should be analyzed
61  *
62  * NOTE(Evgenii Kudriashov): Prior to walking the graph in steps 5 and 6, We
63  * need to perform static cycle elimination on the constraint graph, as well as
64  * off-line variable substitution.
65  *
66  * NOTE(Evgenii Kudriashov): To add flow-sensitivity the "Flow-sensitive
67  * pointer analysis for millions of lines of code" by Ben Hardekopf and Calvin
68  * Lin may be considered.
69  *
70  * NOTE(Evgenii Kudriashov): After implementing VRP and SCEV the "Loop-Oriented
71  * Array- and Field-Sensitive Pointer Analysis for Automatic SIMD
72  * Vectorization" by Yulei Sui, Xiaokang Fan, Hao Zhou, and Jingling Xue may be
73  * considered to add advanced analysis of array indices.
74  */
75 
76 namespace ark::compiler {
77 
AliasAnalysis(Graph * graph)78 AliasAnalysis::AliasAnalysis(Graph *graph) : Analysis(graph), pointsTo_(graph->GetAllocator()->Adapter()) {}
79 
GetBlocksToVisit() const80 const ArenaVector<BasicBlock *> &AliasAnalysis::GetBlocksToVisit() const
81 {
82     return GetGraph()->GetBlocksRPO();
83 }
84 
RunImpl()85 bool AliasAnalysis::RunImpl()
86 {
87     Init();
88 
89     VisitGraph();
90 
91     // Initialize solution sets
92     for (auto pair : *direct_) {
93         auto it = pointsTo_.try_emplace(pair.first, GetGraph()->GetAllocator()->Adapter());
94         ASSERT(pair.first.GetBase() == nullptr || pair.first.GetBase()->GetOpcode() != Opcode::NullCheck);
95         ASSERT(pair.second.GetBase() == nullptr || pair.second.GetBase()->GetOpcode() != Opcode::NullCheck);
96         it.first->second.insert(pair.second);
97     }
98 
99     // Build graph
100     for (auto pair : *copy_) {
101         auto it = chains_->try_emplace(pair.first, GetGraph()->GetLocalAllocator()->Adapter());
102         ASSERT(pair.first.GetBase() == nullptr || pair.first.GetBase()->GetOpcode() != Opcode::NullCheck);
103         ASSERT(pair.second.GetBase() == nullptr || pair.second.GetBase()->GetOpcode() != Opcode::NullCheck);
104         it.first->second.push_back(pair.second);
105     }
106 
107     SolveConstraints();
108 
109 #ifndef NDEBUG
110     if (CompilerLogger::IsComponentEnabled(CompilerLoggerComponents::ALIAS_ANALYSIS)) {
111         std::ostringstream out;
112         DumpChains(&out);
113         Dump(&out);
114         COMPILER_LOG(DEBUG, ALIAS_ANALYSIS) << out.str();
115     }
116 #endif
117     return true;
118 }
119 
Init()120 void AliasAnalysis::Init()
121 {
122     auto allocator = GetGraph()->GetLocalAllocator();
123     chains_ = allocator->New<PointerMap<ArenaVector<Pointer>>>(allocator->Adapter());
124     direct_ = allocator->New<PointerPairVector>(allocator->Adapter());
125     copy_ = allocator->New<PointerPairVector>(allocator->Adapter());
126     inputsSet_ = allocator->New<ArenaSet<Inst *>>(allocator->Adapter());
127     ASSERT(chains_ != nullptr);
128     ASSERT(direct_ != nullptr);
129     ASSERT(copy_ != nullptr);
130     ASSERT(inputsSet_ != nullptr);
131     pointsTo_.clear();
132 }
133 
Dump(std::ostream * out) const134 void Pointer::Dump(std::ostream *out) const
135 {
136     switch (type_) {
137         case OBJECT:
138             (*out) << "v" << base_->GetId();
139             break;
140         case STATIC_FIELD:
141             (*out) << "SF #" << imm_;
142             break;
143         case POOL_CONSTANT:
144             (*out) << "PC #" << imm_;
145             break;
146         case OBJECT_FIELD:
147             (*out) << "v" << base_->GetId() << " #" << imm_;
148             break;
149         case ARRAY_ELEMENT:
150             (*out) << "v" << base_->GetId() << "[";
151             if (idx_ != nullptr) {
152                 (*out) << "v" << idx_->GetId();
153                 if (imm_ != 0) {
154                     (*out) << "+" << imm_;
155                 }
156             } else {
157                 (*out) << imm_;
158             }
159             (*out) << "]";
160             break;
161         case DICTIONARY_ELEMENT:
162             (*out) << "v" << base_->GetId() << "[";
163             (*out) << "v" << idx_->GetId();
164             if (imm_ != 0) {
165                 (*out) << "#NAME";
166             } else {
167                 (*out) << "#INDEX";
168             }
169             (*out) << "]";
170             break;
171         default:
172             UNREACHABLE();
173     }
174     if (local_) {
175         (*out) << "(local)";
176     }
177     if (volatile_) {
178         (*out) << "(v)";
179     }
180 }
181 
PointerLess(const Pointer & lhs,const Pointer & rhs)182 static bool PointerLess(const Pointer &lhs, const Pointer &rhs)
183 {
184     if (lhs.GetBase() == rhs.GetBase()) {
185         return lhs.GetImm() < rhs.GetImm();
186     }
187     if (lhs.GetBase() == nullptr) {
188         return true;
189     }
190     if (rhs.GetBase() == nullptr) {
191         return false;
192     }
193     return lhs.GetBase()->GetId() < rhs.GetBase()->GetId();
194 }
195 
GetDynamicAccessPointer(Inst * inst,Inst * base,DynObjectAccessType type,DynObjectAccessMode mode)196 static Pointer GetDynamicAccessPointer(Inst *inst, Inst *base, DynObjectAccessType type, DynObjectAccessMode mode)
197 {
198     if (type == DynObjectAccessType::UNKNOWN || mode == DynObjectAccessMode::UNKNOWN) {
199         return Pointer::CreateObject(base);
200     }
201 
202     Inst *idx = inst->GetDataFlowInput(1);
203     uint64_t imm = 0;
204     if (type == DynObjectAccessType::BY_NAME) {
205         ASSERT_DO(mode != DynObjectAccessMode::ARRAY,
206                   (std::cerr << "Unexpected access type BY_NAME for access mode ARRAY: ", inst->Dump(&std::cerr)));
207         imm = UINT64_MAX;
208     } else {
209         ASSERT_DO(type == DynObjectAccessType::BY_INDEX,
210                   (std::cerr << "Unsupported dynamic access type in alias analysis: ", inst->Dump(&std::cerr)));
211     }
212     if (mode == DynObjectAccessMode::ARRAY) {
213         return Pointer::CreateArrayElement(base, idx, imm);
214     }
215     ASSERT_DO(mode == DynObjectAccessMode::DICTIONARY,
216               (std::cerr << "Unsupported dynamic access mode in alias analysis: ", inst->Dump(&std::cerr)));
217     return Pointer::CreateDictionaryElement(base, idx, imm);
218 }
219 
DumpChains(std::ostream * out) const220 void AliasAnalysis::DumpChains(std::ostream *out) const
221 {
222     ArenaVector<Pointer> sortedKeys(GetGraph()->GetLocalAllocator()->Adapter());
223     for (auto &pair : *chains_) {
224         sortedKeys.push_back(pair.first);
225     }
226     if (sortedKeys.empty()) {
227         (*out) << "\nThe chains is empty" << std::endl;
228         return;
229     }
230     std::sort(sortedKeys.begin(), sortedKeys.end(), PointerLess);
231 
232     (*out) << "\nThe chains are the following: {" << std::endl;
233     for (auto &p : sortedKeys) {
234         (*out) << "\t";
235         p.Dump(out);
236         (*out) << ": {";
237 
238         // Sort by instruction ID to add more readability to logs
239         ArenaVector<Pointer> sorted(chains_->at(p), GetGraph()->GetLocalAllocator()->Adapter());
240         std::sort(sorted.begin(), sorted.end(), PointerLess);
241         auto edge = sorted.begin();
242         if (edge != sorted.end()) {
243             edge->Dump(out);
244             while (++edge != sorted.end()) {
245                 (*out) << ", ";
246                 edge->Dump(out);
247             }
248         }
249         (*out) << "}" << std::endl;
250     }
251     (*out) << "}" << std::endl;
252 }
253 
DumpDirect(std::ostream * out) const254 void AliasAnalysis::DumpDirect(std::ostream *out) const
255 {
256     (*out) << "\nThe direct are the following:" << std::endl;
257     for (auto &pair : *direct_) {
258         (*out) << "{ ";
259         pair.first.Dump(out);
260         (*out) << " , ";
261         pair.second.Dump(out);
262         (*out) << " }" << std::endl;
263     }
264 }
265 
DumpCopy(std::ostream * out) const266 void AliasAnalysis::DumpCopy(std::ostream *out) const
267 {
268     (*out) << "\nThe copy are the following:" << std::endl;
269     for (auto &pair : *copy_) {
270         (*out) << "{ ";
271         pair.first.Dump(out);
272         (*out) << " , ";
273         pair.second.Dump(out);
274         (*out) << " }" << std::endl;
275     }
276 }
277 
Dump(std::ostream * out) const278 void AliasAnalysis::Dump(std::ostream *out) const
279 {
280     ArenaVector<Pointer> sortedKeys(GetGraph()->GetLocalAllocator()->Adapter());
281     for (auto &pair : pointsTo_) {
282         sortedKeys.push_back(pair.first);
283     }
284     if (sortedKeys.empty()) {
285         (*out) << "\nThe solution set is empty" << std::endl;
286         return;
287     }
288     std::sort(sortedKeys.begin(), sortedKeys.end(), PointerLess);
289 
290     (*out) << "\nThe solution set is the following:" << std::endl;
291     for (auto &p : sortedKeys) {
292         (*out) << "\t";
293         p.Dump(out);
294         (*out) << ": {";
295 
296         // Sort by instruction ID to add more readability to logs
297         auto values = pointsTo_.at(p);
298         ArenaVector<Pointer> sorted(values.begin(), values.end(), GetGraph()->GetLocalAllocator()->Adapter());
299         std::sort(sorted.begin(), sorted.end(), PointerLess);
300         auto iter = sorted.begin();
301         if (iter != sorted.end()) {
302             iter->Dump(out);
303             while (++iter != sorted.end()) {
304                 (*out) << ", ";
305                 iter->Dump(out);
306             }
307         }
308         (*out) << "}" << std::endl;
309     }
310 }
311 
CheckInstAlias(Inst * mem1,Inst * mem2) const312 AliasType AliasAnalysis::CheckInstAlias(Inst *mem1, Inst *mem2) const
313 {
314     ASSERT(mem1->IsMemory() && mem2->IsMemory());
315     Pointer p1 = {};
316     Pointer p2 = {};
317 
318     if (!ParseInstruction(mem1, &p1) || !ParseInstruction(mem2, &p2)) {
319         return MAY_ALIAS;
320     }
321 
322     // Instructions with different types cannot alias each other. Handle
323     // difference only in numeric types for now.
324     if (IsTypeNumeric(mem1->GetType()) && IsTypeNumeric(mem2->GetType()) &&
325         GetTypeSize(mem1->GetType(), GetGraph()->GetArch()) != GetTypeSize(mem2->GetType(), GetGraph()->GetArch())) {
326         return NO_ALIAS;
327     }
328     // Instructions with a primitive type and the reference type cannot alias each other.
329     if ((IsTypeNumeric(mem1->GetType()) && mem2->IsReferenceOrAny()) ||
330         (IsTypeNumeric(mem2->GetType()) && mem1->IsReferenceOrAny())) {
331         return NO_ALIAS;
332     }
333 
334     return CheckMemAddress(p1, p2);
335 }
336 
CheckRefAlias(Inst * ref1,Inst * ref2) const337 AliasType AliasAnalysis::CheckRefAlias(Inst *ref1, Inst *ref2) const
338 {
339     ASSERT(ref1->IsReferenceOrAny());
340     ASSERT(ref2->IsReferenceOrAny());
341     return CheckMemAddress(Pointer::CreateObject(ref1), Pointer::CreateObject(ref2));
342 }
343 
CheckMemAddressEmptyIntersectionCase(const PointerSet & aliases1,const PointerSet & aliases2,const Pointer & p1,const Pointer & p2) const344 AliasType AliasAnalysis::CheckMemAddressEmptyIntersectionCase(const PointerSet &aliases1, const PointerSet &aliases2,
345                                                               const Pointer &p1, const Pointer &p2) const
346 {
347     // If at least one set of aliases consists of only local aliases then there is NO_ALIAS
348     auto isOuter = [](Pointer const &p) { return !p.IsLocal(); };
349     if (std::find_if(aliases1.begin(), aliases1.end(), isOuter) == aliases1.end() ||
350         std::find_if(aliases2.begin(), aliases2.end(), isOuter) == aliases2.end()) {
351         return NO_ALIAS;
352     }
353     // Different fields cannot alias each other even if they are not created locally
354     if (p1.GetType() == OBJECT_FIELD && !p1.HasSameOffset(p2)) {
355         return NO_ALIAS;
356     }
357     if (p1.GetType() == ARRAY_ELEMENT) {
358         auto equal = IsSameOffsets(p1.GetIdx(), p2.GetIdx());
359         // If it is known that indices are different OR Imm indices are different then there is
360         // no alias.  If they are both different we can't certainly say so.
361         if ((equal == Trilean::FALSE && p1.GetImm() == p2.GetImm()) ||
362             (equal == Trilean::TRUE && p1.GetImm() != p2.GetImm())) {
363             return NO_ALIAS;
364         }
365     }
366     if (p1.GetType() == DICTIONARY_ELEMENT) {
367         auto equal = IsSameOffsets(p1.GetIdx(), p2.GetIdx());
368         if (equal == Trilean::FALSE && p1.GetImm() == p2.GetImm()) {
369             return NO_ALIAS;
370         }
371     }
372     return MAY_ALIAS;
373 }
374 
375 /**
376  * We have 5 types of pointers: OBJECT, OBJECT_FIELD, POOL_CONSTANT,
377  * STATIC_FIELD and ARRAY_ELEMENT.  They correspond to groups of memory storing
378  * and loading instructions.  Assuming that these groups cannot load the same
379  * memory address (at IR level), it is true that different types of pointers
380  * cannot alias each other.
381  *
382  * Global pointers such as STATIC_FIELD and POOL_CONSTANT are checked through
383  * their unique TypeId.
384  *
385  * For OBJECT_FIELDs we look at objects they referenced to.  If they refer to
386  * the same objects then depending on TypeId they MUST_ALIAS or NO_ALIAS.  If
387  * the situation of the referenced objects is unclear then they MAY_ALIAS.
388  *
389  * The same is for ARRAY_ELEMENT.  Instead of TypeId we look at index and compare them.
390  *
391  * All function's arguments MAY_ALIAS each other.  Created objects in the
392  * function may not alias arguments.
393  */
CheckMemAddress(const Pointer & p1,const Pointer & p2) const394 AliasType AliasAnalysis::CheckMemAddress(const Pointer &p1, const Pointer &p2) const
395 {
396     if (p1.GetType() != p2.GetType()) {
397         return NO_ALIAS;
398     }
399 
400     if (p1.GetType() == STATIC_FIELD || p2.GetType() == STATIC_FIELD || p1.GetType() == POOL_CONSTANT ||
401         p2.GetType() == POOL_CONSTANT) {
402         if (p1.HasSameOffset(p2)) {
403             return MUST_ALIAS;
404         }
405         return NO_ALIAS;
406     }
407 
408     auto baseObj1 = Pointer::CreateObject(p1.GetBase());
409     auto baseObj2 = Pointer::CreateObject(p2.GetBase());
410     ASSERT_DO(pointsTo_.find(baseObj1) != pointsTo_.end(),
411               (std::cerr << "Undefined inst in AliasAnalysis: ", p1.GetBase()->Dump(&std::cerr)));
412     ASSERT_DO(pointsTo_.find(baseObj2) != pointsTo_.end(),
413               (std::cerr << "Undefined inst in AliasAnalysis: ", p2.GetBase()->Dump(&std::cerr)));
414     auto &aliases1 = pointsTo_.at(baseObj1);
415     auto &aliases2 = pointsTo_.at(baseObj2);
416     // Find the intersection
417     const Pointer *intersection = nullptr;
418     for (auto &alias : aliases1) {
419         if (aliases2.find(alias) != aliases2.end()) {
420             intersection = &alias;
421             break;
422         }
423     }
424 
425     // The only common intersection
426     if (intersection != nullptr && aliases1.size() == 1 && aliases2.size() == 1) {
427         return SingleIntersectionAliasing(p1, p2, intersection);
428     }
429     // Empty intersection: check that both addresses are not parameters
430     if (intersection == nullptr) {
431         return CheckMemAddressEmptyIntersectionCase(aliases1, aliases2, p1, p2);
432     }
433     return MAY_ALIAS;
434 }
435 
CombineIdxAndImm(const Pointer * p)436 static uint64_t CombineIdxAndImm(const Pointer *p)
437 {
438     uint64_t sum = 0;
439     if (p->GetIdx() != nullptr) {
440         auto idx = p->GetIdx();
441         ASSERT(idx->IsConst());
442         ASSERT(!DataType::IsFloatType(idx->GetType()));
443         sum = idx->CastToConstant()->GetRawValue();
444     }
445     sum += p->GetImm();
446     return sum;
447 }
448 
AliasingTwoArrayPointers(const Pointer * p1,const Pointer * p2)449 AliasType AliasAnalysis::AliasingTwoArrayPointers(const Pointer *p1, const Pointer *p2)
450 {
451     // Structure of Pointer: base, idx, imm
452     // Base is same. We should compare fields in order: idx, combine {idx + imm}.
453     // Is necessary compare sum, because LoadArrayI (..., nullptr, 2) and StoreArray(..., Const{2}, 0) will alias,
454     // but in separate idx and imm are different.
455 
456     // 1) Compare idx. If they same, compare Imm part -> MUST_ALIAS, NO_ALIAS
457     if (AliasAnalysis::IsSameOffsets(p1->GetIdx(), p2->GetIdx()) == Trilean::TRUE) {
458         return p1->GetImm() == p2->GetImm() ? MUST_ALIAS : NO_ALIAS;
459     }
460     // 2) If still one of indexes is not constant or nullptr -> MAY_ALIAS
461     for (auto *pointer : {p1, p2}) {
462         if (pointer->GetIdx() != nullptr && !pointer->GetIdx()->IsConst()) {
463             return MAY_ALIAS;
464         }
465     }
466     // 3) Combine idx(is constant) and imm for compare
467     if (CombineIdxAndImm(p1) == CombineIdxAndImm(p2)) {
468         return MUST_ALIAS;
469     }
470     return NO_ALIAS;
471 }
472 
473 /// Checks aliasing if P1 and P2 point to the one single object.
474 /* static */
SingleIntersectionAliasing(const Pointer & p1,const Pointer & p2,const Pointer * intersection)475 AliasType AliasAnalysis::SingleIntersectionAliasing(const Pointer &p1, const Pointer &p2, const Pointer *intersection)
476 {
477     ASSERT(p1.GetType() == p2.GetType());
478     switch (p1.GetType()) {
479         case ARRAY_ELEMENT: {
480             return AliasingTwoArrayPointers(&p1, &p2);
481         }
482         case DICTIONARY_ELEMENT:
483             // It is dinamic case, there are less guarantees
484             if (IsSameOffsets(p1.GetIdx(), p2.GetIdx()) != Trilean::TRUE) {
485                 return MAY_ALIAS;
486             }
487             if (p1.GetImm() != p2.GetImm()) {
488                 return MAY_ALIAS;
489             }
490             break;
491         case OBJECT_FIELD:
492             if (!p1.HasSameOffset(p2)) {
493                 return NO_ALIAS;
494             }
495             break;
496         case OBJECT:
497             break;
498         default:
499             UNREACHABLE();
500     }
501     if (intersection->IsVolatile()) {
502         return MAY_ALIAS;
503     }
504     return MUST_ALIAS;
505 }
506 
SolveConstraintsMainLoop(Pointer & ref,Pointer & edge,bool & added,PointerSet & sols)507 void AliasAnalysis::SolveConstraintsMainLoop(Pointer &ref, Pointer &edge, bool &added, PointerSet &sols)
508 {
509     for (auto &alias : pointsTo_.at(ref)) {
510         ASSERT(alias.GetBase() == nullptr || alias.GetBase()->GetOpcode() != Opcode::NullCheck);
511         if (edge.GetType() == OBJECT_FIELD && ref.GetBase() == edge.GetBase()) {
512             // Propagating from object to fields: A{a} -> A.F{a.f}
513             if (alias.GetType() == OBJECT) {
514                 Pointer p = Pointer::CreateObjectField(alias.GetBase(), edge.GetImm(), edge.GetTypePtr());
515                 p.SetLocalVolatile(alias.IsLocal(), edge.IsVolatile());
516 
517                 added |= sols.insert(p).second;
518                 continue;
519             }
520             // In case A{a.g} -> A.F we propagate symbolic name: A{a.g} -> A.F{A.F}
521             Pointer p = Pointer::CreateObjectField(ref.GetBase(), edge.GetImm(), edge.GetTypePtr());
522             p.SetLocalVolatile(alias.IsLocal(), edge.IsVolatile());
523 
524             added |= sols.insert(p).second;
525             continue;
526         }
527         if (edge.GetType() == ARRAY_ELEMENT && ref.GetBase() == edge.GetBase()) {
528             // Propagating from object to elements: A{a} -> A[i]{a[i]}
529             if (alias.GetType() == OBJECT) {
530                 Pointer p = Pointer::CreateArrayElement(alias.GetBase(), edge.GetIdx(), edge.GetImm());
531                 p.SetLocalVolatile(alias.IsLocal(), edge.IsVolatile());
532 
533                 added |= sols.insert(p).second;
534                 continue;
535             }
536             // In case A{a[j]} -> A[i] we propagate symbolic name: A{a[j]} -> A[i]{A[i]}
537             Pointer p = Pointer::CreateArrayElement(ref.GetBase(), edge.GetIdx(), edge.GetImm());
538             p.SetLocalVolatile(alias.IsLocal(), edge.IsVolatile());
539 
540             added |= sols.insert(p).second;
541             continue;
542         }
543         if (edge.GetType() == DICTIONARY_ELEMENT && ref.GetBase() == edge.GetBase()) {
544             // Propagating from object to elements: A{a} -> A[i]{a[i]}
545             if (alias.GetType() == OBJECT) {
546                 Pointer p = Pointer::CreateDictionaryElement(alias.GetBase(), edge.GetIdx());
547                 p.SetLocalVolatile(alias.IsLocal(), edge.IsVolatile());
548 
549                 added |= sols.insert(p).second;
550                 continue;
551             }
552             // In case A{a[j]} -> A[i] we propagate symbolic name: A{a[j]} -> A[i]{A[i]}
553             Pointer p = Pointer::CreateDictionaryElement(ref.GetBase(), edge.GetIdx());
554             p.SetLocalVolatile(alias.IsLocal(), edge.IsVolatile());
555 
556             added |= sols.insert(p).second;
557             continue;
558         }
559         added |= sols.insert(alias).second;
560     }
561 }
562 
563 /**
564  * Here we propagate solutions obtained from direct constraints through copy
565  * constraints e.g: we have a node A with solution {a} and the node A was
566  * copied to B and C (this->chains_ maintains these links), and C was copied to
567  * D.
568  *
569  *    A{a} -> B
570  *        \-> C -> D
571  *
572  * After first iteration (iterating A node) we will obtain
573  *
574  *     A{a} -> B{a}
575  *         \-> C{a} -> D
576  *
577  * After second iteration (iterating B node) nothing changes
578  *
579  * After third iteration (iterating C node):
580  *
581  * A{a} -> B{a}
582  *     \-> C{a} -> D{a}
583  *
584  * For complex nodes (OBJECT_FIELD, ARRAY_ELEMENT) we create auxiliary nodes e.g.
585  * if a field F was accessed from object A then we have two nodes:
586  *
587  * A{a} -> A.F
588  *
589  * And solutions from A would be propagated as following:
590  *
591  * A{a} -> A.F{a.F}
592  *
593  * The function works using worklist to process only updated nodes.
594  */
SolveConstraints()595 void AliasAnalysis::SolveConstraints()
596 {
597     ArenaQueue<Pointer> worklist(GetGraph()->GetLocalAllocator()->Adapter());
598     for (auto &pair : *direct_) {
599         if (chains_->find(pair.first) != chains_->end()) {
600             worklist.push(pair.first);
601         }
602     }
603 
604     while (!worklist.empty()) {
605         Pointer &ref = worklist.front();
606         ASSERT(ref.GetBase() == nullptr || ref.GetBase()->GetOpcode() != Opcode::NullCheck);
607         for (auto &edge : chains_->at(ref)) {
608             // POOL_CONSTANT cannot be assignee
609             ASSERT(edge.GetType() != POOL_CONSTANT);
610             auto &sols = pointsTo_.try_emplace(edge, GetGraph()->GetAllocator()->Adapter()).first->second;
611             bool added = false;
612 
613             SolveConstraintsMainLoop(ref, edge, added, sols);
614 
615             if (added && chains_->find(edge) != chains_->end()) {
616                 worklist.push(edge);
617             }
618             ASSERT(!sols.empty());
619         }
620         worklist.pop();
621     }
622 }
623 
624 /// Selects the address from instruction that should be checked on alias
ParseInstruction(Inst * inst,Pointer * pointer)625 bool AliasAnalysis::ParseInstruction(Inst *inst, Pointer *pointer)
626 {
627     Pointer p {};
628     switch (inst->GetOpcode()) {
629         case Opcode::LoadArray:
630         case Opcode::LoadArrayI:
631         case Opcode::StoreArray:
632         case Opcode::StoreArrayI:
633             p = ParseArrayElement(inst);
634             break;
635         case Opcode::LoadString:
636         case Opcode::LoadType:
637         case Opcode::UnresolvedLoadType:
638             p = ParsePoolConstant(inst);
639             break;
640         case Opcode::LoadStatic:
641         case Opcode::StoreStatic:
642         case Opcode::UnresolvedStoreStatic:
643         case Opcode::LoadResolvedObjectFieldStatic:
644         case Opcode::StoreResolvedObjectFieldStatic:
645             p = ParseStaticField(inst);
646             break;
647         case Opcode::LoadObject:
648         case Opcode::StoreObject:
649         case Opcode::LoadResolvedObjectField:
650         case Opcode::StoreResolvedObjectField:
651             p = ParseObjectField(inst);
652             break;
653         case Opcode::LoadObjectDynamic:
654         case Opcode::StoreObjectDynamic:
655             p = ParseDynamicField(inst);
656             break;
657         default:
658             return false;
659     }
660 
661     auto base = p.GetBase();
662     if (base != nullptr) {
663         // Currently unhandled and return always MAY_ALIAS
664         if (base->GetOpcode() == Opcode::LoadArrayPair || base->GetOpcode() == Opcode::LoadArrayPairI ||
665             base->GetOpcode() == Opcode::LoadPairPart || base->GetOpcode() == Opcode::CatchPhi ||
666             base->GetOpcode() == Opcode::Load || base->GetOpcode() == Opcode::LoadI ||
667             base->GetOpcode() == Opcode::Store || base->GetOpcode() == Opcode::StoreI) {
668             return false;
669         }
670     }
671 
672     *pointer = p;
673     return true;
674 }
675 
ParseArrayElement(Inst * inst)676 Pointer AliasAnalysis::ParseArrayElement(Inst *inst)
677 {
678     uint32_t imm = 0;
679     Inst *offset = nullptr;
680     switch (inst->GetOpcode()) {
681         case Opcode::LoadArray:
682         case Opcode::StoreArray:
683             offset = inst->GetDataFlowInput(1);
684             break;
685         case Opcode::LoadArrayI:
686             imm = inst->CastToLoadArrayI()->GetImm();
687             break;
688         case Opcode::StoreArrayI:
689             imm = inst->CastToStoreArrayI()->GetImm();
690             break;
691         default:
692             UNREACHABLE();
693     }
694     auto base = inst->GetDataFlowInput(0);
695     return Pointer::CreateArrayElement(base, offset, imm);
696 }
697 
ParsePoolConstant(Inst * inst)698 Pointer AliasAnalysis::ParsePoolConstant(Inst *inst)
699 {
700     uint32_t typeId = 0;
701     switch (inst->GetOpcode()) {
702         case Opcode::LoadString:
703             typeId = inst->CastToLoadString()->GetTypeId();
704             break;
705         case Opcode::LoadType:
706             typeId = inst->CastToLoadType()->GetTypeId();
707             break;
708         case Opcode::UnresolvedLoadType:
709             typeId = inst->CastToUnresolvedLoadType()->GetTypeId();
710             break;
711         default:
712             UNREACHABLE();
713     }
714     return Pointer::CreatePoolConstant(typeId);
715 }
716 
ParseStaticField(Inst * inst)717 Pointer AliasAnalysis::ParseStaticField(Inst *inst)
718 {
719     uint32_t typeId = 0;
720     void *typePtr = nullptr;
721     switch (inst->GetOpcode()) {
722         case Opcode::LoadStatic:
723             typeId = inst->CastToLoadStatic()->GetTypeId();
724             typePtr = inst->CastToLoadStatic()->GetObjField();
725             break;
726         case Opcode::LoadResolvedObjectFieldStatic:
727             typeId = inst->CastToLoadResolvedObjectFieldStatic()->GetTypeId();
728             break;
729         case Opcode::StoreStatic:
730             typeId = inst->CastToStoreStatic()->GetTypeId();
731             typePtr = inst->CastToStoreStatic()->GetObjField();
732             break;
733         case Opcode::UnresolvedStoreStatic:
734             typeId = inst->CastToUnresolvedStoreStatic()->GetTypeId();
735             break;
736         case Opcode::StoreResolvedObjectFieldStatic:
737             typeId = inst->CastToStoreResolvedObjectFieldStatic()->GetTypeId();
738             break;
739         default:
740             UNREACHABLE();
741     }
742     return Pointer::CreateStaticField(typeId, typePtr);
743 }
744 
ParseObjectField(Inst * inst)745 Pointer AliasAnalysis::ParseObjectField(Inst *inst)
746 {
747     uint32_t typeId = 0;
748     void *typePtr = nullptr;
749     bool isStatic = false;
750     switch (inst->GetOpcode()) {
751         case Opcode::LoadObject:
752             isStatic = inst->CastToLoadObject()->GetObjectType() == ObjectType::MEM_STATIC;
753             typeId = inst->CastToLoadObject()->GetTypeId();
754             typePtr = inst->CastToLoadObject()->GetObjField();
755             break;
756         case Opcode::LoadResolvedObjectField:
757             typeId = inst->CastToLoadResolvedObjectField()->GetTypeId();
758             break;
759         case Opcode::StoreObject:
760             isStatic = inst->CastToStoreObject()->GetObjectType() == ObjectType::MEM_STATIC;
761             typeId = inst->CastToStoreObject()->GetTypeId();
762             typePtr = inst->CastToStoreObject()->GetObjField();
763             break;
764         case Opcode::StoreResolvedObjectField:
765             typeId = inst->CastToStoreResolvedObjectField()->GetTypeId();
766             break;
767         default:
768             UNREACHABLE();
769     }
770     auto base = inst->GetDataFlowInput(0);
771     return isStatic ? Pointer::CreateStaticField(typeId, typePtr) : Pointer::CreateObjectField(base, typeId, typePtr);
772 }
773 
ParseDynamicField(Inst * inst)774 Pointer AliasAnalysis::ParseDynamicField(Inst *inst)
775 {
776     auto base = inst->GetDataFlowInput(0);
777 
778     DynObjectAccessType type;
779     DynObjectAccessMode mode;
780     switch (inst->GetOpcode()) {
781         case Opcode::LoadObjectDynamic:
782             type = inst->CastToLoadObjectDynamic()->GetAccessType();
783             mode = inst->CastToLoadObjectDynamic()->GetAccessMode();
784             break;
785         case Opcode::StoreObjectDynamic:
786             type = inst->CastToStoreObjectDynamic()->GetAccessType();
787             mode = inst->CastToStoreObjectDynamic()->GetAccessMode();
788             break;
789         default:
790             UNREACHABLE();
791     }
792 
793     return GetDynamicAccessPointer(inst, base, type, mode);
794 }
795 
796 /**
797  * Compares offsets. Since we have a situation when we cannot determine either equal offsets or not,
798  * we use three valued logic. It is handy when we want to know whether offsets are definitely
799  * different or definitely equal.
800  */
801 /* static */
IsSameOffsets(const Inst * off1,const Inst * off2)802 AliasAnalysis::Trilean AliasAnalysis::IsSameOffsets(const Inst *off1, const Inst *off2)
803 {
804     if (off1 == off2) {
805         return Trilean::TRUE;
806     }
807     if (off1 == nullptr || off2 == nullptr) {
808         return Trilean::FALSE;
809     }
810 
811     if (off1->GetVN() != INVALID_VN && off2->GetVN() != INVALID_VN && off1->GetVN() == off2->GetVN()) {
812         return Trilean::TRUE;
813     }
814 
815     if (off1->IsConst() && off2->IsConst() &&
816         off1->CastToConstant()->GetRawValue() != off2->CastToConstant()->GetRawValue()) {
817         return Trilean::FALSE;
818     }
819 
820     return Trilean::UNKNOWN;
821 }
822 
823 /// Instructions that definitely are not an alias of anything.
VisitNullPtr(GraphVisitor * v,Inst * inst)824 void AliasAnalysis::VisitNullPtr(GraphVisitor *v, Inst *inst)
825 {
826     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
827 }
VisitLoadUndefined(GraphVisitor * v,Inst * inst)828 void AliasAnalysis::VisitLoadUndefined(GraphVisitor *v, Inst *inst)
829 {
830     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
831 }
VisitInitObject(GraphVisitor * v,Inst * inst)832 void AliasAnalysis::VisitInitObject(GraphVisitor *v, Inst *inst)
833 {
834     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
835 }
VisitNewObject(GraphVisitor * v,Inst * inst)836 void AliasAnalysis::VisitNewObject(GraphVisitor *v, Inst *inst)
837 {
838     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
839 }
VisitNewArray(GraphVisitor * v,Inst * inst)840 void AliasAnalysis::VisitNewArray(GraphVisitor *v, Inst *inst)
841 {
842     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
843 }
VisitMultiArray(GraphVisitor * v,Inst * inst)844 void AliasAnalysis::VisitMultiArray(GraphVisitor *v, Inst *inst)
845 {
846     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
847 }
VisitInitEmptyString(GraphVisitor * v,Inst * inst)848 void AliasAnalysis::VisitInitEmptyString(GraphVisitor *v, Inst *inst)
849 {
850     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
851 }
VisitInitString(GraphVisitor * v,Inst * inst)852 void AliasAnalysis::VisitInitString(GraphVisitor *v, Inst *inst)
853 {
854     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
855 }
856 
857 /**
858  * Instructions that can introduce references that are an alias of
859  * something already existed.
860  */
VisitConstant(GraphVisitor * v,Inst * inst)861 void AliasAnalysis::VisitConstant(GraphVisitor *v, Inst *inst)
862 {
863     if (inst->IsReferenceOrAny()) {
864         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
865     }
866 }
VisitParameter(GraphVisitor * v,Inst * inst)867 void AliasAnalysis::VisitParameter(GraphVisitor *v, Inst *inst)
868 {
869     if (inst->IsReferenceOrAny()) {
870         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
871     }
872 }
VisitLoadImmediate(GraphVisitor * v,Inst * inst)873 void AliasAnalysis::VisitLoadImmediate(GraphVisitor *v, Inst *inst)
874 {
875     if (inst->IsReferenceOrAny()) {
876         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
877     }
878 }
VisitIntrinsic(GraphVisitor * v,Inst * inst)879 void AliasAnalysis::VisitIntrinsic(GraphVisitor *v, Inst *inst)
880 {
881     if (inst->IsReferenceOrAny()) {
882         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
883     }
884 }
VisitBuiltin(GraphVisitor * v,Inst * inst)885 void AliasAnalysis::VisitBuiltin(GraphVisitor *v, Inst *inst)
886 {
887     if (inst->IsReferenceOrAny()) {
888         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
889     }
890 }
VisitCallStatic(GraphVisitor * v,Inst * inst)891 void AliasAnalysis::VisitCallStatic(GraphVisitor *v, Inst *inst)
892 {
893     if (inst->IsReferenceOrAny()) {
894         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
895     }
896 }
VisitCallResolvedStatic(GraphVisitor * v,Inst * inst)897 void AliasAnalysis::VisitCallResolvedStatic(GraphVisitor *v, Inst *inst)
898 {
899     if (inst->IsReferenceOrAny()) {
900         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
901     }
902 }
VisitCallVirtual(GraphVisitor * v,Inst * inst)903 void AliasAnalysis::VisitCallVirtual(GraphVisitor *v, Inst *inst)
904 {
905     if (inst->IsReferenceOrAny()) {
906         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
907     }
908 }
VisitCallResolvedVirtual(GraphVisitor * v,Inst * inst)909 void AliasAnalysis::VisitCallResolvedVirtual(GraphVisitor *v, Inst *inst)
910 {
911     if (inst->IsReferenceOrAny()) {
912         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
913     }
914 }
VisitCallDynamic(GraphVisitor * v,Inst * inst)915 void AliasAnalysis::VisitCallDynamic(GraphVisitor *v, Inst *inst)
916 {
917     if (inst->IsReferenceOrAny()) {
918         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
919     }
920 }
VisitGetManagedClassObject(GraphVisitor * v,Inst * inst)921 void AliasAnalysis::VisitGetManagedClassObject(GraphVisitor *v, Inst *inst)
922 {
923     if (inst->IsReferenceOrAny()) {
924         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
925     }
926 }
VisitResolveObjectFieldStatic(GraphVisitor * v,Inst * inst)927 void AliasAnalysis::VisitResolveObjectFieldStatic(GraphVisitor *v, Inst *inst)
928 {
929     if (inst->IsReferenceOrAny()) {
930         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
931     }
932 }
933 
VisitBitcast(GraphVisitor * v,Inst * inst)934 void AliasAnalysis::VisitBitcast(GraphVisitor *v, Inst *inst)
935 {
936     if (inst->IsReferenceOrAny()) {
937         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
938     }
939 }
940 
941 /// Instructions that introduce static fields (global variables).
VisitLoadStatic(GraphVisitor * v,Inst * inst)942 void AliasAnalysis::VisitLoadStatic(GraphVisitor *v, Inst *inst)
943 {
944     if (!inst->IsReferenceOrAny()) {
945         return;
946     }
947     auto visitor = static_cast<AliasAnalysis *>(v);
948     auto typedInst = inst->CastToLoadStatic();
949     uint32_t typeId = typedInst->GetTypeId();
950     Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
951 
952     sfield.SetVolatile(typedInst->GetVolatile());
953 
954     visitor->AddDirectEdge(sfield);
955     visitor->AddCopyEdge(sfield, Pointer::CreateObject(inst));
956 }
957 
VisitLoadResolvedObjectFieldStatic(GraphVisitor * v,Inst * inst)958 void AliasAnalysis::VisitLoadResolvedObjectFieldStatic(GraphVisitor *v, Inst *inst)
959 {
960     if (!inst->IsReferenceOrAny()) {
961         return;
962     }
963     auto visitor = static_cast<AliasAnalysis *>(v);
964     auto typedInst = inst->CastToLoadResolvedObjectFieldStatic();
965     uint32_t typeId = typedInst->GetTypeId();
966     Pointer sfield = Pointer::CreateStaticField(typeId);
967 
968     sfield.SetVolatile(IsVolatileMemInst(typedInst));
969 
970     visitor->AddDirectEdge(sfield);
971     visitor->AddCopyEdge(sfield, Pointer::CreateObject(inst));
972 }
973 
VisitStoreStatic(GraphVisitor * v,Inst * inst)974 void AliasAnalysis::VisitStoreStatic(GraphVisitor *v, Inst *inst)
975 {
976     if (!inst->IsReferenceOrAny()) {
977         return;
978     }
979     auto visitor = static_cast<AliasAnalysis *>(v);
980     auto typedInst = inst->CastToStoreStatic();
981     uint32_t typeId = typedInst->GetTypeId();
982     Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
983 
984     sfield.SetVolatile(typedInst->GetVolatile());
985 
986     visitor->AddDirectEdge(sfield);
987     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), sfield);
988 }
989 
VisitStoreResolvedObjectFieldStatic(GraphVisitor * v,Inst * inst)990 void AliasAnalysis::VisitStoreResolvedObjectFieldStatic(GraphVisitor *v, Inst *inst)
991 {
992     if (inst->GetType() != DataType::REFERENCE) {
993         return;
994     }
995     auto visitor = static_cast<AliasAnalysis *>(v);
996     auto typedInst = inst->CastToStoreResolvedObjectFieldStatic();
997     uint32_t typeId = typedInst->GetTypeId();
998     Pointer sfield = Pointer::CreateStaticField(typeId);
999 
1000     sfield.SetVolatile(IsVolatileMemInst(typedInst));
1001 
1002     visitor->AddDirectEdge(sfield);
1003     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), sfield);
1004 }
1005 
VisitUnresolvedStoreStatic(GraphVisitor * v,Inst * inst)1006 void AliasAnalysis::VisitUnresolvedStoreStatic(GraphVisitor *v, Inst *inst)
1007 {
1008     if (!inst->IsReferenceOrAny()) {
1009         return;
1010     }
1011     auto visitor = static_cast<AliasAnalysis *>(v);
1012     auto typedInst = inst->CastToUnresolvedStoreStatic();
1013     uint32_t typeId = typedInst->GetTypeId();
1014     Pointer sfield = Pointer::CreateStaticField(typeId);
1015 
1016     sfield.SetVolatile(IsVolatileMemInst(typedInst));
1017 
1018     visitor->AddDirectEdge(sfield);
1019     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), sfield);
1020 }
1021 
1022 /// Instructions that introduce unique constant references (global constants).
VisitLoadRuntimeClass(GraphVisitor * v,Inst * inst)1023 void AliasAnalysis::VisitLoadRuntimeClass(GraphVisitor *v, Inst *inst)
1024 {
1025     if (inst->IsReferenceOrAny()) {
1026         uint32_t typeId = inst->CastToLoadRuntimeClass()->GetTypeId();
1027         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1028     }
1029 }
1030 
VisitLoadClass(GraphVisitor * v,Inst * inst)1031 void AliasAnalysis::VisitLoadClass(GraphVisitor *v, Inst *inst)
1032 {
1033     if (inst->IsReferenceOrAny()) {
1034         uint32_t typeId = inst->CastToLoadClass()->GetTypeId();
1035         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1036     }
1037 }
VisitLoadAndInitClass(GraphVisitor * v,Inst * inst)1038 void AliasAnalysis::VisitLoadAndInitClass(GraphVisitor *v, Inst *inst)
1039 {
1040     if (inst->IsReferenceOrAny()) {
1041         uint32_t typeId = inst->CastToLoadAndInitClass()->GetTypeId();
1042         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1043     }
1044 }
VisitUnresolvedLoadAndInitClass(GraphVisitor * v,Inst * inst)1045 void AliasAnalysis::VisitUnresolvedLoadAndInitClass(GraphVisitor *v, Inst *inst)
1046 {
1047     if (inst->IsReferenceOrAny()) {
1048         uint32_t typeId = inst->CastToUnresolvedLoadAndInitClass()->GetTypeId();
1049         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1050     }
1051 }
VisitGetGlobalVarAddress(GraphVisitor * v,Inst * inst)1052 void AliasAnalysis::VisitGetGlobalVarAddress(GraphVisitor *v, Inst *inst)
1053 {
1054     if (inst->IsReferenceOrAny()) {
1055         uint32_t typeId = inst->CastToGetGlobalVarAddress()->GetTypeId();
1056         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1057     }
1058 }
VisitLoadString(GraphVisitor * v,Inst * inst)1059 void AliasAnalysis::VisitLoadString(GraphVisitor *v, Inst *inst)
1060 {
1061     if (inst->IsReferenceOrAny()) {
1062         uint32_t typeId = inst->CastToLoadString()->GetTypeId();
1063         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1064     }
1065 }
VisitLoadConstArray(GraphVisitor * v,Inst * inst)1066 void AliasAnalysis::VisitLoadConstArray(GraphVisitor *v, Inst *inst)
1067 {
1068     if (inst->IsReferenceOrAny()) {
1069         uint32_t typeId = inst->CastToLoadConstArray()->GetTypeId();
1070         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1071     }
1072 }
VisitLoadType(GraphVisitor * v,Inst * inst)1073 void AliasAnalysis::VisitLoadType(GraphVisitor *v, Inst *inst)
1074 {
1075     if (inst->IsReferenceOrAny()) {
1076         uint32_t typeId = inst->CastToLoadType()->GetTypeId();
1077         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1078     }
1079 }
VisitUnresolvedLoadType(GraphVisitor * v,Inst * inst)1080 void AliasAnalysis::VisitUnresolvedLoadType(GraphVisitor *v, Inst *inst)
1081 {
1082     if (inst->IsReferenceOrAny()) {
1083         uint32_t typeId = inst->CastToUnresolvedLoadType()->GetTypeId();
1084         static_cast<AliasAnalysis *>(v)->AddConstantDirectEdge(inst, typeId);
1085     }
1086 }
1087 
VisitLoadObjFromConst(GraphVisitor * v,Inst * inst)1088 void AliasAnalysis::VisitLoadObjFromConst(GraphVisitor *v, Inst *inst)
1089 {
1090     if (inst->IsReferenceOrAny()) {
1091         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
1092     }
1093 }
1094 
1095 /// Instructions that introduce aliases.
VisitLoadArray(GraphVisitor * v,Inst * inst)1096 void AliasAnalysis::VisitLoadArray(GraphVisitor *v, Inst *inst)
1097 {
1098     if (!inst->IsReferenceOrAny()) {
1099         return;
1100     }
1101     auto visitor = static_cast<AliasAnalysis *>(v);
1102     Inst *arr = inst->GetDataFlowInput(0);
1103     Inst *idx = inst->GetDataFlowInput(1);
1104     Pointer obj = Pointer::CreateObject(arr);
1105     Pointer elem = Pointer::CreateArrayElement(arr, idx);
1106     Pointer val = Pointer::CreateObject(inst);
1107 
1108     visitor->AddCopyEdge(obj, elem);
1109     visitor->AddCopyEdge(elem, val);
1110 }
1111 
VisitStoreArray(GraphVisitor * v,Inst * inst)1112 void AliasAnalysis::VisitStoreArray(GraphVisitor *v, Inst *inst)
1113 {
1114     if (!inst->IsReferenceOrAny()) {
1115         return;
1116     }
1117     auto visitor = static_cast<AliasAnalysis *>(v);
1118     Inst *arr = inst->GetDataFlowInput(0);
1119     Inst *idx = inst->GetDataFlowInput(1);
1120     Pointer obj = Pointer::CreateObject(arr);
1121     Pointer elem = Pointer::CreateArrayElement(arr, idx);
1122     Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(2U));
1123 
1124     visitor->AddCopyEdge(obj, elem);
1125     visitor->AddCopyEdge(val, elem);
1126 }
1127 
VisitLoadArrayI(GraphVisitor * v,Inst * inst)1128 void AliasAnalysis::VisitLoadArrayI(GraphVisitor *v, Inst *inst)
1129 {
1130     if (!inst->IsReferenceOrAny()) {
1131         return;
1132     }
1133     auto visitor = static_cast<AliasAnalysis *>(v);
1134     Inst *arr = inst->GetDataFlowInput(0);
1135     Pointer obj = Pointer::CreateObject(arr);
1136     Pointer elem = Pointer::CreateArrayElement(arr, nullptr, inst->CastToLoadArrayI()->GetImm());
1137     Pointer val = Pointer::CreateObject(inst);
1138 
1139     visitor->AddCopyEdge(obj, elem);
1140     visitor->AddCopyEdge(elem, val);
1141 }
1142 
VisitStoreArrayI(GraphVisitor * v,Inst * inst)1143 void AliasAnalysis::VisitStoreArrayI(GraphVisitor *v, Inst *inst)
1144 {
1145     if (!inst->IsReferenceOrAny()) {
1146         return;
1147     }
1148     auto visitor = static_cast<AliasAnalysis *>(v);
1149     Inst *arr = inst->GetDataFlowInput(0);
1150     Pointer obj = Pointer::CreateObject(arr);
1151     Pointer elem = Pointer::CreateArrayElement(arr, nullptr, inst->CastToStoreArrayI()->GetImm());
1152     Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(1));
1153 
1154     visitor->AddCopyEdge(obj, elem);
1155     visitor->AddCopyEdge(val, elem);
1156 }
1157 
VisitLoadArrayPair(GraphVisitor * v,Inst * inst)1158 void AliasAnalysis::VisitLoadArrayPair(GraphVisitor *v, Inst *inst)
1159 {
1160     if (!inst->IsReferenceOrAny()) {
1161         return;
1162     }
1163     auto visitor = static_cast<AliasAnalysis *>(v);
1164     auto *load = inst->CastToLoadArrayPair();
1165     Inst *arr = load->GetDataFlowInput(load->GetArray());
1166     Pointer obj = Pointer::CreateObject(arr);
1167     for (auto &user : load->GetUsers()) {
1168         ASSERT(user.GetInst()->GetOpcode() == Opcode::LoadPairPart);
1169         auto uinst = user.GetInst()->CastToLoadPairPart();
1170 
1171         Pointer elem = Pointer::CreateArrayElement(arr, load->GetIndex(), uinst->GetImm());
1172         Pointer val = Pointer::CreateObject(uinst);
1173         visitor->AddCopyEdge(obj, elem);
1174         visitor->AddCopyEdge(elem, val);
1175         visitor->AddCopyEdge(elem, Pointer::CreateObject(load));
1176     }
1177 }
1178 
VisitStoreArrayPair(GraphVisitor * v,Inst * inst)1179 void AliasAnalysis::VisitStoreArrayPair(GraphVisitor *v, Inst *inst)
1180 {
1181     if (!inst->IsReferenceOrAny()) {
1182         return;
1183     }
1184     auto visitor = static_cast<AliasAnalysis *>(v);
1185     auto *store = inst->CastToStoreArrayPair();
1186     Inst *arr = store->GetDataFlowInput(store->GetArray());
1187     Pointer obj = Pointer::CreateObject(arr);
1188     Pointer elFst = Pointer::CreateArrayElement(arr, store->GetIndex());
1189     Pointer elSnd = Pointer::CreateArrayElement(arr, store->GetIndex(), 1);
1190     Pointer valFst = Pointer::CreateObject(store->GetDataFlowInput(store->GetStoredValue(0)));
1191     Pointer valSnd = Pointer::CreateObject(store->GetDataFlowInput(store->GetStoredValue(1)));
1192 
1193     visitor->AddCopyEdge(obj, elFst);
1194     visitor->AddCopyEdge(obj, elSnd);
1195     visitor->AddCopyEdge(valFst, elFst);
1196     visitor->AddCopyEdge(valSnd, elSnd);
1197 }
1198 
VisitLoadObjectPair(GraphVisitor * v,Inst * inst)1199 void AliasAnalysis::VisitLoadObjectPair(GraphVisitor *v, Inst *inst)
1200 {
1201     if (!inst->IsReferenceOrAny()) {
1202         return;
1203     }
1204     auto visitor = static_cast<AliasAnalysis *>(v);
1205     auto typedInst = inst->CastToLoadObjectPair();
1206     uint32_t typeId0 = typedInst->GetTypeId0();
1207     uint32_t typeId1 = typedInst->GetTypeId1();
1208     ASSERT(typedInst->GetObjectType() != ObjectType::MEM_STATIC);
1209     Inst *dfobj = inst->GetDataFlowInput(0);
1210     Pointer obj = Pointer::CreateObject(dfobj);
1211     Pointer field0 = Pointer::CreateObjectField(dfobj, typeId0, typedInst->GetObjField0());
1212     Pointer field1 = Pointer::CreateObjectField(dfobj, typeId1, typedInst->GetObjField1());
1213 
1214     Pointer to = Pointer::CreateObject(inst);
1215 
1216     field0.SetVolatile(typedInst->GetVolatile());
1217     field1.SetVolatile(typedInst->GetVolatile());
1218 
1219     visitor->AddCopyEdge(obj, field0);
1220     visitor->AddCopyEdge(field0, to);
1221     visitor->AddCopyEdge(obj, field1);
1222     visitor->AddCopyEdge(field1, to);
1223 
1224     for (auto &user : inst->GetUsers()) {
1225         visitor->AddCopyEdge(obj, Pointer::CreateObject(user.GetInst()));
1226     }
1227 }
1228 
VisitStoreObjectPair(GraphVisitor * v,Inst * inst)1229 void AliasAnalysis::VisitStoreObjectPair(GraphVisitor *v, Inst *inst)
1230 {
1231     if (!inst->IsReferenceOrAny()) {
1232         return;
1233     }
1234     auto visitor = static_cast<AliasAnalysis *>(v);
1235     auto typedInst = inst->CastToStoreObjectPair();
1236     uint32_t typeId0 = typedInst->GetTypeId0();
1237     uint32_t typeId1 = typedInst->GetTypeId1();
1238     ASSERT(typedInst->GetObjectType() != ObjectType::MEM_STATIC);
1239     Inst *dfobj = inst->GetDataFlowInput(0);
1240     Pointer obj = Pointer::CreateObject(dfobj);
1241     Pointer field0 = Pointer::CreateObjectField(dfobj, typeId0, typedInst->GetObjField0());
1242     Pointer val0 = Pointer::CreateObject(inst->GetDataFlowInput(1));
1243     Pointer field1 = Pointer::CreateObjectField(dfobj, typeId1, typedInst->GetObjField1());
1244     Pointer val1 = Pointer::CreateObject(inst->GetDataFlowInput(2));
1245 
1246     field0.SetVolatile(typedInst->GetVolatile());
1247     field1.SetVolatile(typedInst->GetVolatile());
1248 
1249     visitor->AddCopyEdge(obj, field0);
1250     visitor->AddCopyEdge(val0, field0);
1251     visitor->AddCopyEdge(obj, field1);
1252     visitor->AddCopyEdge(val1, field1);
1253 }
1254 
VisitLoadArrayPairI(GraphVisitor * v,Inst * inst)1255 void AliasAnalysis::VisitLoadArrayPairI(GraphVisitor *v, Inst *inst)
1256 {
1257     if (!inst->IsReferenceOrAny()) {
1258         return;
1259     }
1260     auto visitor = static_cast<AliasAnalysis *>(v);
1261     auto *load = inst->CastToLoadArrayPairI();
1262     Inst *arr = load->GetDataFlowInput(load->GetArray());
1263     Pointer obj = Pointer::CreateObject(arr);
1264     for (auto &user : load->GetUsers()) {
1265         ASSERT(user.GetInst()->GetOpcode() == Opcode::LoadPairPart);
1266         auto uinst = user.GetInst()->CastToLoadPairPart();
1267 
1268         Pointer elem = Pointer::CreateArrayElement(arr, nullptr, load->GetImm() + uinst->GetImm());
1269         Pointer val = Pointer::CreateObject(uinst);
1270         visitor->AddCopyEdge(obj, elem);
1271         visitor->AddCopyEdge(elem, val);
1272         visitor->AddCopyEdge(elem, Pointer::CreateObject(load));
1273     }
1274 }
1275 
VisitStoreArrayPairI(GraphVisitor * v,Inst * inst)1276 void AliasAnalysis::VisitStoreArrayPairI(GraphVisitor *v, Inst *inst)
1277 {
1278     if (!inst->IsReferenceOrAny()) {
1279         return;
1280     }
1281     auto visitor = static_cast<AliasAnalysis *>(v);
1282     auto *store = inst->CastToStoreArrayPairI();
1283     Inst *arr = store->GetDataFlowInput(store->GetArray());
1284     Pointer obj = Pointer::CreateObject(arr);
1285     Pointer elFst = Pointer::CreateArrayElement(arr, nullptr, store->GetImm());
1286     Pointer elSnd = Pointer::CreateArrayElement(arr, nullptr, store->GetImm() + 1);
1287     Pointer valFst = Pointer::CreateObject(store->GetDataFlowInput(store->GetFirstValue()));
1288     Pointer valSnd = Pointer::CreateObject(store->GetDataFlowInput(store->GetSecondValue()));
1289 
1290     visitor->AddCopyEdge(obj, elFst);
1291     visitor->AddCopyEdge(obj, elSnd);
1292     visitor->AddCopyEdge(valFst, elFst);
1293     visitor->AddCopyEdge(valSnd, elSnd);
1294 }
1295 
VisitLoadObject(GraphVisitor * v,Inst * inst)1296 void AliasAnalysis::VisitLoadObject(GraphVisitor *v, Inst *inst)
1297 {
1298     if (!inst->IsReferenceOrAny()) {
1299         return;
1300     }
1301     auto visitor = static_cast<AliasAnalysis *>(v);
1302     auto typedInst = inst->CastToLoadObject();
1303     uint32_t typeId = typedInst->GetTypeId();
1304     if (inst->CastToLoadObject()->GetObjectType() == ObjectType::MEM_STATIC) {
1305         Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
1306 
1307         sfield.SetVolatile(typedInst->GetVolatile());
1308 
1309         visitor->AddDirectEdge(sfield);
1310         visitor->AddCopyEdge(sfield, Pointer::CreateObject(inst));
1311     } else {
1312         Inst *dfobj = inst->GetDataFlowInput(0);
1313         Pointer obj = Pointer::CreateObject(dfobj);
1314         Pointer ifield = Pointer::CreateObjectField(dfobj, typeId, typedInst->GetObjField());
1315         Pointer to = Pointer::CreateObject(inst);
1316 
1317         ifield.SetVolatile(typedInst->GetVolatile());
1318 
1319         visitor->AddCopyEdge(obj, ifield);
1320         visitor->AddCopyEdge(ifield, to);
1321     }
1322 }
1323 
VisitLoadResolvedObjectField(GraphVisitor * v,Inst * inst)1324 void AliasAnalysis::VisitLoadResolvedObjectField(GraphVisitor *v, Inst *inst)
1325 {
1326     if (!inst->IsReferenceOrAny()) {
1327         return;
1328     }
1329     auto visitor = static_cast<AliasAnalysis *>(v);
1330     auto typedInst = inst->CastToLoadResolvedObjectField();
1331     uint32_t typeId = typedInst->GetTypeId();
1332     Inst *dfobj = inst->GetDataFlowInput(0);
1333     Pointer obj = Pointer::CreateObject(dfobj);
1334     Pointer ifield = Pointer::CreateObjectField(dfobj, typeId);
1335     Pointer to = Pointer::CreateObject(inst);
1336 
1337     ifield.SetVolatile(IsVolatileMemInst(typedInst));
1338 
1339     visitor->AddCopyEdge(obj, ifield);
1340     visitor->AddCopyEdge(ifield, to);
1341 }
1342 
VisitStoreObject(GraphVisitor * v,Inst * inst)1343 void AliasAnalysis::VisitStoreObject(GraphVisitor *v, Inst *inst)
1344 {
1345     if (!inst->IsReferenceOrAny()) {
1346         return;
1347     }
1348     auto visitor = static_cast<AliasAnalysis *>(v);
1349     auto typedInst = inst->CastToStoreObject();
1350     uint32_t typeId = typedInst->GetTypeId();
1351     if (inst->CastToStoreObject()->GetObjectType() == ObjectType::MEM_STATIC) {
1352         Pointer sfield = Pointer::CreateStaticField(typeId, typedInst->GetObjField());
1353 
1354         sfield.SetVolatile(typedInst->GetVolatile());
1355 
1356         visitor->AddDirectEdge(sfield);
1357         visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), sfield);
1358     } else {
1359         Inst *dfobj = inst->GetDataFlowInput(0);
1360         Pointer obj = Pointer::CreateObject(dfobj);
1361         Pointer ifield = Pointer::CreateObjectField(dfobj, typeId, typedInst->GetObjField());
1362         Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(1));
1363 
1364         ifield.SetVolatile(typedInst->GetVolatile());
1365 
1366         visitor->AddCopyEdge(obj, ifield);
1367         visitor->AddCopyEdge(val, ifield);
1368     }
1369 }
1370 
VisitStoreResolvedObjectField(GraphVisitor * v,Inst * inst)1371 void AliasAnalysis::VisitStoreResolvedObjectField(GraphVisitor *v, Inst *inst)
1372 {
1373     if (!inst->IsReferenceOrAny()) {
1374         return;
1375     }
1376     auto visitor = static_cast<AliasAnalysis *>(v);
1377     auto typedInst = inst->CastToStoreResolvedObjectField();
1378     uint32_t typeId = typedInst->GetTypeId();
1379     Inst *dfobj = inst->GetDataFlowInput(0);
1380     Pointer obj = Pointer::CreateObject(dfobj);
1381     Pointer ifield = Pointer::CreateObjectField(dfobj, typeId);
1382     Pointer val = Pointer::CreateObject(inst->GetDataFlowInput(1));
1383 
1384     ifield.SetVolatile(IsVolatileMemInst(inst));
1385 
1386     visitor->AddCopyEdge(obj, ifield);
1387     visitor->AddCopyEdge(val, ifield);
1388 }
1389 
VisitCatchPhi(GraphVisitor * v,Inst * inst)1390 void AliasAnalysis::VisitCatchPhi(GraphVisitor *v, Inst *inst)
1391 {
1392     if (!inst->IsReferenceOrAny()) {
1393         return;
1394     }
1395     auto visitor = static_cast<AliasAnalysis *>(v);
1396     auto inputsSet = visitor->GetClearInputsSet();
1397     for (size_t i = 0; i < inst->GetInputsCount(); i++) {
1398         inputsSet->insert(inst->GetDataFlowInput(i));
1399     }
1400 
1401     for (auto inputInst : *inputsSet) {
1402         visitor->AddCopyEdge(Pointer::CreateObject(inputInst), Pointer::CreateObject(inst));
1403     }
1404 }
1405 
VisitPhi(GraphVisitor * v,Inst * inst)1406 void AliasAnalysis::VisitPhi(GraphVisitor *v, Inst *inst)
1407 {
1408     if (!inst->IsReferenceOrAny()) {
1409         return;
1410     }
1411     auto visitor = static_cast<AliasAnalysis *>(v);
1412     for (size_t i = 0; i < inst->GetInputsCount(); i++) {
1413         visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(i)), Pointer::CreateObject(inst));
1414     }
1415 }
1416 
VisitSelect(GraphVisitor * v,Inst * inst)1417 void AliasAnalysis::VisitSelect(GraphVisitor *v, Inst *inst)
1418 {
1419     if (!inst->IsReferenceOrAny()) {
1420         return;
1421     }
1422     ASSERT(inst->GetInputsCount() == 4U);
1423     auto visitor = static_cast<AliasAnalysis *>(v);
1424     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), Pointer::CreateObject(inst));
1425     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(1)), Pointer::CreateObject(inst));
1426 }
1427 
VisitSelectImm(GraphVisitor * v,Inst * inst)1428 void AliasAnalysis::VisitSelectImm(GraphVisitor *v, Inst *inst)
1429 {
1430     if (!inst->IsReferenceOrAny()) {
1431         return;
1432     }
1433     ASSERT(inst->GetInputsCount() == 3U);
1434     auto visitor = static_cast<AliasAnalysis *>(v);
1435     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), Pointer::CreateObject(inst));
1436     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(1)), Pointer::CreateObject(inst));
1437 }
1438 
VisitMov(GraphVisitor * v,Inst * inst)1439 void AliasAnalysis::VisitMov(GraphVisitor *v, Inst *inst)
1440 {
1441     if (!inst->IsReferenceOrAny()) {
1442         return;
1443     }
1444     auto visitor = static_cast<AliasAnalysis *>(v);
1445     visitor->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)), Pointer::CreateObject(inst));
1446 }
1447 
VisitCastAnyTypeValue(GraphVisitor * v,Inst * inst)1448 void AliasAnalysis::VisitCastAnyTypeValue(GraphVisitor *v, Inst *inst)
1449 {
1450     if (inst->GetType() == DataType::REFERENCE) {
1451         static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
1452     }
1453 }
1454 
VisitCastValueToAnyType(GraphVisitor * v,Inst * inst)1455 void AliasAnalysis::VisitCastValueToAnyType(GraphVisitor *v, Inst *inst)
1456 {
1457     if (inst->CastToCastValueToAnyType()->GetInputType(0) == DataType::REFERENCE) {
1458         static_cast<AliasAnalysis *>(v)->AddCopyEdge(Pointer::CreateObject(inst->GetDataFlowInput(0)),
1459                                                      Pointer::CreateObject(inst));
1460     }
1461 }
1462 
VisitGetAnyTypeName(GraphVisitor * v,Inst * inst)1463 void AliasAnalysis::VisitGetAnyTypeName(GraphVisitor *v, Inst *inst)
1464 {
1465     static_cast<AliasAnalysis *>(v)->AddDirectEdge(Pointer::CreateObject(inst));
1466 }
1467 
VisitLoadConstantPool(GraphVisitor * v,Inst * inst)1468 void AliasAnalysis::VisitLoadConstantPool(GraphVisitor *v, Inst *inst)
1469 {
1470     Inst *dfobj = inst->GetDataFlowInput(0);
1471     Pointer obj = Pointer::CreateObject(dfobj);
1472     Pointer to = Pointer::CreateObject(inst);
1473     static_cast<AliasAnalysis *>(v)->AddCopyEdge(obj, to);
1474 }
1475 
VisitLoadLexicalEnv(GraphVisitor * v,Inst * inst)1476 void AliasAnalysis::VisitLoadLexicalEnv(GraphVisitor *v, Inst *inst)
1477 {
1478     Inst *dfobj = inst->GetDataFlowInput(0);
1479     Pointer obj = Pointer::CreateObject(dfobj);
1480     Pointer to = Pointer::CreateObject(inst);
1481     static_cast<AliasAnalysis *>(v)->AddCopyEdge(obj, to);
1482 }
1483 
VisitLoadObjectDynamic(GraphVisitor * v,Inst * inst)1484 void AliasAnalysis::VisitLoadObjectDynamic(GraphVisitor *v, Inst *inst)
1485 {
1486     if (!inst->IsReferenceOrAny()) {
1487         return;
1488     }
1489     auto visitor = static_cast<AliasAnalysis *>(v);
1490     auto type = inst->CastToLoadObjectDynamic()->GetAccessType();
1491     auto mode = inst->CastToLoadObjectDynamic()->GetAccessMode();
1492 
1493     Inst *dfobj = inst->GetDataFlowInput(0);
1494     Pointer obj = Pointer::CreateObject(dfobj);
1495     Pointer val = Pointer::CreateObject(inst);
1496     Pointer elem = GetDynamicAccessPointer(inst, dfobj, type, mode);
1497 
1498     visitor->AddCopyEdge(obj, elem);
1499     visitor->AddCopyEdge(elem, val);
1500 }
1501 
VisitStoreObjectDynamic(GraphVisitor * v,Inst * inst)1502 void AliasAnalysis::VisitStoreObjectDynamic(GraphVisitor *v, Inst *inst)
1503 {
1504     if (!inst->IsReferenceOrAny()) {
1505         return;
1506     }
1507     auto visitor = static_cast<AliasAnalysis *>(v);
1508     auto type = inst->CastToStoreObjectDynamic()->GetAccessType();
1509     auto mode = inst->CastToStoreObjectDynamic()->GetAccessMode();
1510 
1511     Inst *dfobj = inst->GetDataFlowInput(0);
1512     Pointer obj = Pointer::CreateObject(dfobj);
1513     Pointer val = Pointer::CreateObject(inst);
1514     Pointer elem = GetDynamicAccessPointer(inst, dfobj, type, mode);
1515 
1516     visitor->AddCopyEdge(obj, elem);
1517     visitor->AddCopyEdge(val, elem);
1518 }
1519 
VisitLoadFromConstantPool(GraphVisitor * v,Inst * inst)1520 void AliasAnalysis::VisitLoadFromConstantPool(GraphVisitor *v, Inst *inst)
1521 {
1522     if (!inst->IsReferenceOrAny()) {
1523         return;
1524     }
1525     uint32_t typeId = inst->CastToLoadFromConstantPool()->GetTypeId();
1526     auto visitor = static_cast<AliasAnalysis *>(v);
1527     Inst *constpool = inst->GetDataFlowInput(0);
1528     Pointer obj = Pointer::CreateObject(constpool);
1529     Pointer elem = Pointer::CreateArrayElement(constpool, nullptr, typeId);
1530     Pointer val = Pointer::CreateObject(inst);
1531 
1532     visitor->AddCopyEdge(obj, elem);
1533     visitor->AddCopyEdge(elem, val);
1534 }
1535 
VisitDefault(Inst * inst)1536 void AliasAnalysis::VisitDefault([[maybe_unused]] Inst *inst)
1537 {
1538     /* Ignore the following instructions with REFERENCE type intentionally */
1539     switch (inst->GetOpcode()) {
1540         // Handled on its input
1541         case Opcode::LoadPairPart:
1542         // No passes that check class references aliasing
1543         case Opcode::GetInstanceClass:
1544         case Opcode::LoadImmediate:
1545         // NOTE(ekudriashov): Probably should be added
1546         case Opcode::Monitor:
1547         // Mitigated by using GetDataFlowInput
1548         case Opcode::NullCheck:
1549         case Opcode::RefTypeCheck:
1550         case Opcode::AnyTypeCheck:
1551         case Opcode::ObjByIndexCheck:
1552         case Opcode::HclassCheck:
1553         // Irrelevant for analysis
1554         case Opcode::Return:
1555         case Opcode::ReturnI:
1556         // NOTE(compiler team): support Load, Store
1557         case Opcode::Load:
1558         case Opcode::LoadI:
1559         case Opcode::Store:
1560         case Opcode::StoreI:
1561         // No need to analyze
1562         case Opcode::LiveOut:
1563         case Opcode::FunctionImmediate:
1564             return;
1565         default:
1566             ASSERT_DO(!inst->IsReferenceOrAny(),
1567                       (std::cerr << "Unsupported instruction in alias analysis: ", inst->Dump(&std::cerr)));
1568             return;
1569     }
1570 }
1571 }  // namespace ark::compiler
1572