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