1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "analysis.h"
17
18 #include "optimizer/ir/basicblock.h"
19 namespace panda::compiler {
20
21 class BasicBlock;
FindOsrEntryRec(BasicBlock * dominate_bb,BasicBlock * current_bb,Marker mrk)22 bool FindOsrEntryRec(BasicBlock *dominate_bb, BasicBlock *current_bb, Marker mrk)
23 {
24 if (dominate_bb == current_bb) {
25 return false;
26 }
27 if (current_bb->SetMarker(mrk)) {
28 return false;
29 }
30 if (current_bb->IsOsrEntry()) {
31 return true;
32 }
33
34 for (auto pred : current_bb->GetPredsBlocks()) {
35 if (FindOsrEntryRec(dominate_bb, pred, mrk)) {
36 return true;
37 }
38 }
39 return false;
40 }
41
HasOsrEntryBetween(Inst * dominate_inst,Inst * inst)42 bool HasOsrEntryBetween(Inst *dominate_inst, Inst *inst)
43 {
44 auto bb = inst->GetBasicBlock();
45 auto graph = bb->GetGraph();
46 if (!graph->IsOsrMode()) {
47 return false;
48 }
49 auto dominate_bb = dominate_inst->GetBasicBlock();
50
51 auto mrk = graph->NewMarker();
52
53 auto has_osr_entry = FindOsrEntryRec(dominate_bb, bb, mrk);
54
55 graph->EraseMarker(mrk);
56 return has_osr_entry;
57 }
58
InstStoredValue(Inst * inst,Inst ** second_value)59 Inst *InstStoredValue(Inst *inst, Inst **second_value)
60 {
61 ASSERT_PRINT(inst->IsStore(), "Attempt to take a stored value on non-store instruction");
62 Inst *val = nullptr;
63 *second_value = nullptr;
64 switch (inst->GetOpcode()) {
65 case Opcode::StoreArray:
66 case Opcode::StoreObject:
67 case Opcode::StoreStatic:
68 case Opcode::StoreArrayI:
69 case Opcode::Store:
70 case Opcode::StoreI:
71 // Last input is a stored value
72 val = inst->GetInput(inst->GetInputsCount() - 1).GetInst();
73 break;
74 case Opcode::UnresolvedStoreObject:
75 val = inst->GetInput(1).GetInst();
76 break;
77 case Opcode::UnresolvedStoreStatic:
78 val = inst->GetInput(0).GetInst();
79 break;
80 case Opcode::StoreArrayPair:
81 case Opcode::StoreArrayPairI: {
82 val = inst->GetInput(inst->GetInputsCount() - 2U).GetInst();
83 auto second_inst = inst->GetInput(inst->GetInputsCount() - 1U).GetInst();
84 *second_value = inst->GetDataFlowInput(second_inst);
85 break;
86 }
87 // Unhandled store instructions has been met
88 default:
89 UNREACHABLE();
90 }
91 return inst->GetDataFlowInput(val);
92 }
93
InstStoredValue(Inst * inst)94 Inst *InstStoredValue(Inst *inst)
95 {
96 Inst *second_value = nullptr;
97 Inst *val = InstStoredValue(inst, &second_value);
98 ASSERT(second_value == nullptr);
99 return val;
100 }
101
IsSuitableForImplicitNullCheck(const Inst * inst)102 bool IsSuitableForImplicitNullCheck(const Inst *inst)
103 {
104 auto is_compressed_enabled = inst->GetBasicBlock()->GetGraph()->GetRuntime()->IsCompressedStringsEnabled();
105 switch (inst->GetOpcode()) {
106 case Opcode::LoadArray:
107 return inst->CastToLoadArray()->IsArray() || !is_compressed_enabled;
108 case Opcode::LoadArrayI:
109 return inst->CastToLoadArrayI()->IsArray() || !is_compressed_enabled;
110 case Opcode::LoadObject:
111 // case Opcode::UnresolvedLoadObject:
112 case Opcode::StoreObject:
113 // case Opcode::UnresolvedStoreObject:
114 case Opcode::LenArray:
115 case Opcode::StoreArray:
116 case Opcode::StoreArrayI:
117 case Opcode::LoadArrayPair:
118 case Opcode::StoreArrayPair:
119 case Opcode::LoadArrayPairI:
120 case Opcode::StoreArrayPairI:
121 // These instructions access nullptr and produce a signal in place
122 // Note that CallVirtual is not in the list
123 return true;
124 default:
125 return false;
126 }
127 }
128
IsInstNotNull(const Inst * inst)129 bool IsInstNotNull(const Inst *inst)
130 {
131 // Allocations cannot return null pointer
132 if (inst->IsAllocation() || inst->IsNullCheck()) {
133 return true;
134 }
135 auto graph = inst->GetBasicBlock()->GetGraph();
136 auto runtime = graph->GetRuntime();
137 // The object is not null if the method is virtual and the object is first parameter.
138 return !runtime->IsMethodStatic(graph->GetMethod()) && inst->GetOpcode() == Opcode::Parameter &&
139 inst->CastToParameter()->GetArgNumber() == 0;
140 }
141
142 } // namespace panda::compiler
143