• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "compiler_logger.h"
17 #include "optimizer/ir/basicblock.h"
18 #include "memory_barriers.h"
19 
20 namespace ark::compiler {
21 
MergeBarriers()22 void OptimizeMemoryBarriers::MergeBarriers()
23 {
24     if (barriersInsts_.size() <= 1) {
25         barriersInsts_.clear();
26         return;
27     }
28     isApplied_ = true;
29     auto lastBarrierInst = barriersInsts_.back();
30     for (auto inst : barriersInsts_) {
31         inst->ClearFlag(inst_flags::MEM_BARRIER);
32     }
33     lastBarrierInst->SetFlag(inst_flags::MEM_BARRIER);
34     barriersInsts_.clear();
35 }
36 
CheckInst(Inst * inst)37 bool OptimizeMemoryBarriers::CheckInst(Inst *inst)
38 {
39     return (std::find(barriersInsts_.begin(), barriersInsts_.end(), inst) != barriersInsts_.end());
40 }
41 
CheckAllInputs(Inst * inst)42 void OptimizeMemoryBarriers::CheckAllInputs(Inst *inst)
43 {
44     for (auto input : inst->GetInputs()) {
45         if (CheckInst(input.GetInst())) {
46             MergeBarriers();
47             return;
48         }
49     }
50 }
51 
CheckInput(Inst * input)52 void OptimizeMemoryBarriers::CheckInput(Inst *input)
53 {
54     if (CheckInst(input)) {
55         MergeBarriers();
56     }
57 }
58 
CheckTwoInputs(Inst * input1,Inst * input2)59 void OptimizeMemoryBarriers::CheckTwoInputs(Inst *input1, Inst *input2)
60 {
61     if (CheckInst(input1) || CheckInst(input2)) {
62         MergeBarriers();
63     }
64 }
65 
VisitCallStatic(GraphVisitor * v,Inst * inst)66 void OptimizeMemoryBarriers::VisitCallStatic(GraphVisitor *v, Inst *inst)
67 {
68     if (inst->CastToCallStatic()->IsInlined()) {
69         return;
70     }
71     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
72 }
73 
VisitCallIndirect(GraphVisitor * v,Inst * inst)74 void OptimizeMemoryBarriers::VisitCallIndirect(GraphVisitor *v, Inst *inst)
75 {
76     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
77 }
78 
VisitCall(GraphVisitor * v,Inst * inst)79 void OptimizeMemoryBarriers::VisitCall(GraphVisitor *v, Inst *inst)
80 {
81     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
82 }
83 
VisitCallResolvedStatic(GraphVisitor * v,Inst * inst)84 void OptimizeMemoryBarriers::VisitCallResolvedStatic(GraphVisitor *v, Inst *inst)
85 {
86     if (inst->CastToCallResolvedStatic()->IsInlined()) {
87         return;
88     }
89     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
90 }
91 
VisitCallVirtual(GraphVisitor * v,Inst * inst)92 void OptimizeMemoryBarriers::VisitCallVirtual(GraphVisitor *v, Inst *inst)
93 {
94     if (inst->CastToCallVirtual()->IsInlined()) {
95         return;
96     }
97     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
98 }
99 
VisitCallResolvedVirtual(GraphVisitor * v,Inst * inst)100 void OptimizeMemoryBarriers::VisitCallResolvedVirtual(GraphVisitor *v, Inst *inst)
101 {
102     if (inst->CastToCallResolvedVirtual()->IsInlined()) {
103         return;
104     }
105     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
106 }
107 
VisitCallDynamic(GraphVisitor * v,Inst * inst)108 void OptimizeMemoryBarriers::VisitCallDynamic(GraphVisitor *v, Inst *inst)
109 {
110     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
111 }
112 
VisitCallNative(GraphVisitor * v,Inst * inst)113 void OptimizeMemoryBarriers::VisitCallNative(GraphVisitor *v, Inst *inst)
114 {
115     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
116 }
117 
VisitSelect(GraphVisitor * v,Inst * inst)118 void OptimizeMemoryBarriers::VisitSelect(GraphVisitor *v, Inst *inst)
119 {
120     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
121 }
122 
VisitSelectImm(GraphVisitor * v,Inst * inst)123 void OptimizeMemoryBarriers::VisitSelectImm(GraphVisitor *v, Inst *inst)
124 {
125     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
126 }
127 
VisitStoreObject(GraphVisitor * v,Inst * inst)128 void OptimizeMemoryBarriers::VisitStoreObject(GraphVisitor *v, Inst *inst)
129 {
130     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
131 }
132 
VisitStoreObjectPair(GraphVisitor * v,Inst * inst)133 void OptimizeMemoryBarriers::VisitStoreObjectPair(GraphVisitor *v, Inst *inst)
134 {
135     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
136 }
137 
VisitStoreObjectDynamic(GraphVisitor * v,Inst * inst)138 void OptimizeMemoryBarriers::VisitStoreObjectDynamic(GraphVisitor *v, Inst *inst)
139 {
140     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
141 }
142 
VisitStoreArray(GraphVisitor * v,Inst * inst)143 void OptimizeMemoryBarriers::VisitStoreArray(GraphVisitor *v, Inst *inst)
144 {
145     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
146 }
147 
VisitStoreArrayI(GraphVisitor * v,Inst * inst)148 void OptimizeMemoryBarriers::VisitStoreArrayI(GraphVisitor *v, Inst *inst)
149 {
150     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
151 }
152 
VisitStoreStatic(GraphVisitor * v,Inst * inst)153 void OptimizeMemoryBarriers::VisitStoreStatic(GraphVisitor *v, Inst *inst)
154 {
155     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
156 }
157 
VisitStore(GraphVisitor * v,Inst * inst)158 void OptimizeMemoryBarriers::VisitStore(GraphVisitor *v, Inst *inst)
159 {
160     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
161 }
162 
VisitStoreI(GraphVisitor * v,Inst * inst)163 void OptimizeMemoryBarriers::VisitStoreI(GraphVisitor *v, Inst *inst)
164 {
165     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
166 }
167 
VisitStoreResolvedObjectField(GraphVisitor * v,Inst * inst)168 void OptimizeMemoryBarriers::VisitStoreResolvedObjectField(GraphVisitor *v, Inst *inst)
169 {
170     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(1).GetInst());
171 }
172 
VisitStoreResolvedObjectFieldStatic(GraphVisitor * v,Inst * inst)173 void OptimizeMemoryBarriers::VisitStoreResolvedObjectFieldStatic(GraphVisitor *v, Inst *inst)
174 {
175     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(1).GetInst());
176 }
177 
VisitUnresolvedStoreStatic(GraphVisitor * v,Inst * inst)178 void OptimizeMemoryBarriers::VisitUnresolvedStoreStatic(GraphVisitor *v, Inst *inst)
179 {
180     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(0).GetInst());
181 }
182 
VisitStoreArrayPair(GraphVisitor * v,Inst * inst)183 void OptimizeMemoryBarriers::VisitStoreArrayPair(GraphVisitor *v, Inst *inst)
184 {
185     auto val = inst->GetInputsCount() - 1;
186     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(val).GetInst(),
187                                                              inst->GetInput(val - 1).GetInst());
188 }
189 
VisitStoreArrayPairI(GraphVisitor * v,Inst * inst)190 void OptimizeMemoryBarriers::VisitStoreArrayPairI(GraphVisitor *v, Inst *inst)
191 {
192     auto val = inst->GetInputsCount() - 1;
193     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(val).GetInst(),
194                                                              inst->GetInput(val - 1).GetInst());
195 }
196 
GetMemInstForImplicitNullCheck(Inst * inst)197 static Inst *GetMemInstForImplicitNullCheck(Inst *inst)
198 {
199     if (!inst->HasUsers()) {
200         return nullptr;
201     }
202     auto nextInst = inst->GetNext();
203     while (nextInst != nullptr) {
204         if (IsSuitableForImplicitNullCheck(nextInst)) {
205             if (nextInst->GetInput(0) != inst) {
206                 return nullptr;
207             }
208             return nextInst;
209         }
210         if (!nextInst->IsSafeInst()) {
211             return nullptr;
212         }
213         nextInst = nextInst->GetNext();
214     }
215 
216     return nullptr;
217 }
218 
VisitNullCheck(GraphVisitor * v,Inst * inst)219 void OptimizeMemoryBarriers::VisitNullCheck(GraphVisitor *v, Inst *inst)
220 {
221     // NullCheck was hoisted and can't be implicit
222     if (inst->CanDeoptimize()) {
223         return;
224     }
225     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(0).GetInst());
226     auto nc = static_cast<NullCheckInst *>(inst);
227     auto graph = nc->GetBasicBlock()->GetGraph();
228     // NOTE (pishin) support for arm32
229     if (graph->GetArch() == Arch::AARCH32) {
230         return;
231     }
232     if (!g_options.IsCompilerImplicitNullCheck() || graph->IsOsrMode() || graph->IsBytecodeOptimizer()) {
233         return;
234     }
235 
236     auto memInst = GetMemInstForImplicitNullCheck(inst);
237     if (memInst == nullptr) {
238         return;
239     }
240     memInst->SetFlag(compiler::inst_flags::CAN_THROW);
241     nc->SetImplicit(true);
242 }
243 
VisitBoundCheck(GraphVisitor * v,Inst * inst)244 void OptimizeMemoryBarriers::VisitBoundCheck(GraphVisitor *v, Inst *inst)
245 {
246     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
247 }
248 
ApplyGraph()249 void OptimizeMemoryBarriers::ApplyGraph()
250 {
251     barriersInsts_.clear();
252     for (auto bb : GetGraph()->GetBlocksRPO()) {
253         for (auto inst : bb->Insts()) {
254             if (inst->GetFlag(inst_flags::MEM_BARRIER)) {
255                 barriersInsts_.push_back(inst);
256             }
257             this->VisitInstruction(inst);
258         }
259         this->MergeBarriers();
260     }
261 }
262 
RunImpl()263 bool OptimizeMemoryBarriers::RunImpl()
264 {
265     ApplyGraph();
266     return IsApplied();
267 }
268 
269 }  // namespace ark::compiler
270