• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 "string_builder_utils.h"
17 
18 namespace ark::compiler {
19 
IsStringBuilderInstance(Inst * inst)20 bool IsStringBuilderInstance(Inst *inst)
21 {
22     if (inst->GetOpcode() != Opcode::NewObject) {
23         return false;
24     }
25 
26     auto klass = GetObjectClass(inst->CastToNewObject());
27     if (klass == nullptr) {
28         return false;
29     }
30 
31     auto runtime = inst->GetBasicBlock()->GetGraph()->GetRuntime();
32     return runtime->IsClassStringBuilder(klass);
33 }
34 
IsMethodStringConcat(Inst * inst)35 bool IsMethodStringConcat(Inst *inst)
36 {
37     if (inst->GetOpcode() != Opcode::CallStatic && inst->GetOpcode() != Opcode::CallVirtual) {
38         return false;
39     }
40 
41     auto call = static_cast<CallInst *>(inst);
42     if (call->IsInlined()) {
43         return false;
44     }
45 
46     auto runtime = inst->GetBasicBlock()->GetGraph()->GetRuntime();
47     return runtime->IsMethodStringConcat(call->GetCallMethod());
48 }
49 
IsMethodStringBuilderConstructorWithStringArg(Inst * inst)50 bool IsMethodStringBuilderConstructorWithStringArg(Inst *inst)
51 {
52     if (inst->GetOpcode() != Opcode::CallStatic) {
53         return false;
54     }
55 
56     auto call = inst->CastToCallStatic();
57     if (call->IsInlined()) {
58         return false;
59     }
60 
61     auto runtime = inst->GetBasicBlock()->GetGraph()->GetRuntime();
62     return runtime->IsMethodStringBuilderConstructorWithStringArg(call->GetCallMethod());
63 }
64 
IsMethodStringBuilderConstructorWithCharArrayArg(Inst * inst)65 bool IsMethodStringBuilderConstructorWithCharArrayArg(Inst *inst)
66 {
67     if (inst->GetOpcode() != Opcode::CallStatic) {
68         return false;
69     }
70 
71     auto call = inst->CastToCallStatic();
72     if (call->IsInlined()) {
73         return false;
74     }
75 
76     auto runtime = inst->GetBasicBlock()->GetGraph()->GetRuntime();
77     return runtime->IsMethodStringBuilderConstructorWithCharArrayArg(call->GetCallMethod());
78 }
79 
IsStringBuilderToString(Inst * inst)80 bool IsStringBuilderToString(Inst *inst)
81 {
82     auto runtime = inst->GetBasicBlock()->GetGraph()->GetRuntime();
83     if (inst->GetOpcode() == Opcode::CallStatic || inst->GetOpcode() == Opcode::CallVirtual) {
84         auto callInst = static_cast<CallInst *>(inst);
85         return !callInst->IsInlined() && runtime->IsMethodStringBuilderToString(callInst->GetCallMethod());
86     }
87     if (inst->IsIntrinsic()) {
88         auto intrinsic = inst->CastToIntrinsic();
89         return runtime->IsIntrinsicStringBuilderToString(intrinsic->GetIntrinsicId());
90     }
91     return false;
92 }
93 
IsMethodStringBuilderDefaultConstructor(Inst * inst)94 bool IsMethodStringBuilderDefaultConstructor(Inst *inst)
95 {
96     if (inst->GetOpcode() != Opcode::CallStatic) {
97         return false;
98     }
99 
100     auto call = inst->CastToCallStatic();
101     if (call->IsInlined()) {
102         return false;
103     }
104 
105     auto runtime = inst->GetBasicBlock()->GetGraph()->GetRuntime();
106     return runtime->IsMethodStringBuilderDefaultConstructor(call->GetCallMethod());
107 }
108 
InsertBeforeWithSaveState(Inst * inst,Inst * before)109 void InsertBeforeWithSaveState(Inst *inst, Inst *before)
110 {
111     if (inst->RequireState()) {
112         before->InsertBefore(inst->GetSaveState());
113     }
114     before->InsertBefore(inst);
115 }
116 
InsertAfterWithSaveState(Inst * inst,Inst * after)117 void InsertAfterWithSaveState(Inst *inst, Inst *after)
118 {
119     after->InsertAfter(inst);
120     if (inst->RequireState()) {
121         after->InsertAfter(inst->GetSaveState());
122     }
123 }
124 
InsertBeforeWithInputs(Inst * inst,Inst * before)125 void InsertBeforeWithInputs(Inst *inst, Inst *before)
126 {
127     for (auto &input : inst->GetInputs()) {
128         auto inputInst = input.GetInst();
129         if (inputInst->GetBasicBlock() == nullptr) {
130             InsertBeforeWithInputs(inputInst, before);
131         }
132     }
133 
134     if (inst->GetBasicBlock() == nullptr) {
135         before->InsertBefore(inst);
136     }
137 }
138 
HasInput(Inst * inst,const FindInputPredicate & predicate)139 bool HasInput(Inst *inst, const FindInputPredicate &predicate)
140 {
141     // Check if any instruction input satisfy predicate
142 
143     auto found = std::find_if(inst->GetInputs().begin(), inst->GetInputs().end(), predicate);
144     return found != inst->GetInputs().end();
145 }
146 
HasInputPhiRecursively(Inst * inst,Marker visited,const FindInputPredicate & predicate)147 bool HasInputPhiRecursively(Inst *inst, Marker visited, const FindInputPredicate &predicate)
148 {
149     // Check if any instruction input satisfy predicate
150     // All Phi-instruction inputs are checked recursively
151 
152     if (HasInput(inst, predicate)) {
153         return true;
154     }
155 
156     inst->SetMarker(visited);
157 
158     for (auto &input : inst->GetInputs()) {
159         auto inputInst = input.GetInst();
160         if (!inputInst->IsPhi()) {
161             continue;
162         }
163         if (inputInst->IsMarked(visited)) {
164             continue;
165         }
166         if (HasInputPhiRecursively(inputInst, visited, predicate)) {
167             return true;
168         }
169     }
170 
171     return false;
172 }
173 
ResetInputMarkersRecursively(Inst * inst,Marker visited)174 void ResetInputMarkersRecursively(Inst *inst, Marker visited)
175 {
176     // Reset marker for an instruction and all it's inputs recursively
177 
178     if (inst->IsMarked(visited)) {
179         inst->ResetMarker(visited);
180 
181         for (auto &input : inst->GetInputs()) {
182             auto inputInst = input.GetInst();
183             if (inputInst->IsMarked(visited)) {
184                 ResetInputMarkersRecursively(inputInst, visited);
185             }
186         }
187     }
188 }
189 
HasUser(Inst * inst,const FindUserPredicate & predicate)190 bool HasUser(Inst *inst, const FindUserPredicate &predicate)
191 {
192     // Check if instruction is used in a context defined by predicate
193 
194     auto found = std::find_if(inst->GetUsers().begin(), inst->GetUsers().end(), predicate);
195     return found != inst->GetUsers().end();
196 }
197 
HasUserPhiRecursively(Inst * inst,Marker visited,const FindUserPredicate & predicate)198 bool HasUserPhiRecursively(Inst *inst, Marker visited, const FindUserPredicate &predicate)
199 {
200     // Check if instruction is used in a context defined by predicate
201     // All Phi-instruction users are checked recursively
202 
203     if (HasUser(inst, predicate)) {
204         return true;
205     }
206 
207     inst->SetMarker(visited);
208 
209     for (auto &user : inst->GetUsers()) {
210         auto userInst = user.GetInst();
211         if (!userInst->IsPhi()) {
212             continue;
213         }
214         if (userInst->IsMarked(visited)) {
215             continue;
216         }
217         if (HasUserPhiRecursively(userInst, visited, predicate)) {
218             return true;
219         }
220     }
221 
222     return false;
223 }
224 
ResetUserMarkersRecursively(Inst * inst,Marker visited)225 void ResetUserMarkersRecursively(Inst *inst, Marker visited)
226 {
227     // Reset marker for an instruction and all it's users recursively
228 
229     if (inst->IsMarked(visited)) {
230         inst->ResetMarker(visited);
231 
232         for (auto &user : inst->GetUsers()) {
233             auto userInst = user.GetInst();
234             if (userInst->IsMarked(visited)) {
235                 ResetUserMarkersRecursively(userInst, visited);
236             }
237         }
238     }
239 }
240 
SkipSingleUserCheckInstruction(Inst * inst)241 Inst *SkipSingleUserCheckInstruction(Inst *inst)
242 {
243     if (inst->IsCheck() && inst->HasSingleUser()) {
244         inst = inst->GetUsers().Front().GetInst();
245     }
246     return inst;
247 }
248 
249 }  // namespace ark::compiler
250