• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "compiler_logger.h"
17 #include "optimizer/ir/basicblock.h"
18 #include "memory_barriers.h"
19 
20 namespace panda::compiler {
21 
MergeBarriers()22 void OptimizeMemoryBarriers::MergeBarriers()
23 {
24     if (barriers_insts_.size() <= 1) {
25         barriers_insts_.clear();
26         return;
27     }
28     is_applied_ = true;
29     auto last_barrier_inst = barriers_insts_.back();
30     for (auto inst : barriers_insts_) {
31         inst->ClearFlag(inst_flags::MEM_BARRIER);
32     }
33     last_barrier_inst->SetFlag(inst_flags::MEM_BARRIER);
34     barriers_insts_.clear();
35 }
36 
CheckInst(Inst * inst)37 bool OptimizeMemoryBarriers::CheckInst(Inst *inst)
38 {
39     return (std::find(barriers_insts_.begin(), barriers_insts_.end(), inst) != barriers_insts_.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 
VisitUnresolvedCallStatic(GraphVisitor * v,Inst * inst)84 void OptimizeMemoryBarriers::VisitUnresolvedCallStatic(GraphVisitor *v, Inst *inst)
85 {
86     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
87 }
88 
VisitCallVirtual(GraphVisitor * v,Inst * inst)89 void OptimizeMemoryBarriers::VisitCallVirtual(GraphVisitor *v, Inst *inst)
90 {
91     if (inst->CastToCallVirtual()->IsInlined()) {
92         return;
93     }
94     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
95 }
96 
VisitUnresolvedCallVirtual(GraphVisitor * v,Inst * inst)97 void OptimizeMemoryBarriers::VisitUnresolvedCallVirtual(GraphVisitor *v, Inst *inst)
98 {
99     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
100 }
101 
VisitCallDynamic(GraphVisitor * v,Inst * inst)102 void OptimizeMemoryBarriers::VisitCallDynamic(GraphVisitor *v, Inst *inst)
103 {
104     static_cast<OptimizeMemoryBarriers *>(v)->CheckAllInputs(inst);
105 }
106 
VisitSelect(GraphVisitor * v,Inst * inst)107 void OptimizeMemoryBarriers::VisitSelect(GraphVisitor *v, Inst *inst)
108 {
109     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
110 }
111 
VisitSelectImm(GraphVisitor * v,Inst * inst)112 void OptimizeMemoryBarriers::VisitSelectImm(GraphVisitor *v, Inst *inst)
113 {
114     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
115 }
116 
VisitStoreObject(GraphVisitor * v,Inst * inst)117 void OptimizeMemoryBarriers::VisitStoreObject(GraphVisitor *v, Inst *inst)
118 {
119     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
120 }
121 
VisitStoreArray(GraphVisitor * v,Inst * inst)122 void OptimizeMemoryBarriers::VisitStoreArray(GraphVisitor *v, Inst *inst)
123 {
124     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
125 }
126 
VisitStoreArrayI(GraphVisitor * v,Inst * inst)127 void OptimizeMemoryBarriers::VisitStoreArrayI(GraphVisitor *v, Inst *inst)
128 {
129     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
130 }
131 
VisitStoreStatic(GraphVisitor * v,Inst * inst)132 void OptimizeMemoryBarriers::VisitStoreStatic(GraphVisitor *v, Inst *inst)
133 {
134     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
135 }
136 
VisitStore(GraphVisitor * v,Inst * inst)137 void OptimizeMemoryBarriers::VisitStore(GraphVisitor *v, Inst *inst)
138 {
139     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
140 }
141 
VisitStoreI(GraphVisitor * v,Inst * inst)142 void OptimizeMemoryBarriers::VisitStoreI(GraphVisitor *v, Inst *inst)
143 {
144     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(inst->GetInputsCount() - 1).GetInst());
145 }
146 
VisitUnresolvedStoreObject(GraphVisitor * v,Inst * inst)147 void OptimizeMemoryBarriers::VisitUnresolvedStoreObject(GraphVisitor *v, Inst *inst)
148 {
149     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(1).GetInst());
150 }
151 
VisitUnresolvedStoreStatic(GraphVisitor * v,Inst * inst)152 void OptimizeMemoryBarriers::VisitUnresolvedStoreStatic(GraphVisitor *v, Inst *inst)
153 {
154     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(0).GetInst());
155 }
156 
VisitStoreArrayPair(GraphVisitor * v,Inst * inst)157 void OptimizeMemoryBarriers::VisitStoreArrayPair(GraphVisitor *v, Inst *inst)
158 {
159     auto val = inst->GetInputsCount() - 1;
160     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(val).GetInst(),
161                                                              inst->GetInput(val - 1).GetInst());
162 }
163 
VisitStoreArrayPairI(GraphVisitor * v,Inst * inst)164 void OptimizeMemoryBarriers::VisitStoreArrayPairI(GraphVisitor *v, Inst *inst)
165 {
166     auto val = inst->GetInputsCount() - 1;
167     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(val).GetInst(),
168                                                              inst->GetInput(val - 1).GetInst());
169 }
170 
GetMemInstForImplicitNullCheck(Inst * inst)171 static Inst *GetMemInstForImplicitNullCheck(Inst *inst)
172 {
173     if (!inst->HasUsers()) {
174         return nullptr;
175     }
176     auto nextInst = inst->GetNext();
177     while (nextInst != nullptr) {
178         if (IsSuitableForImplicitNullCheck(nextInst)) {
179             if (nextInst->GetInput(0).GetInst() != inst) {
180                 return nullptr;
181             }
182             return nextInst;
183         }
184         if (!nextInst->IsSafeInst()) {
185             return nullptr;
186         }
187         nextInst = nextInst->GetNext();
188     }
189 
190     return nullptr;
191 }
192 
VisitNullCheck(GraphVisitor * v,Inst * inst)193 void OptimizeMemoryBarriers::VisitNullCheck(GraphVisitor *v, Inst *inst)
194 {
195     static_cast<OptimizeMemoryBarriers *>(v)->CheckInput(inst->GetInput(0).GetInst());
196     auto nc = static_cast<NullCheckInst *>(inst);
197     auto graph = nc->GetBasicBlock()->GetGraph();
198     // TODO (pishin) support for arm32
199     if (graph->GetArch() == Arch::AARCH32) {
200         return;
201     }
202     if (!options.IsCompilerImplicitNullCheck() || graph->IsOsrMode() || graph->IsBytecodeOptimizer()) {
203         return;
204     }
205 
206     auto memInst = GetMemInstForImplicitNullCheck(inst);
207     if (memInst == nullptr) {
208         return;
209     }
210     memInst->SetFlag(compiler::inst_flags::CAN_THROW);
211     nc->SetImplicit(true);
212 }
213 
VisitBoundCheck(GraphVisitor * v,Inst * inst)214 void OptimizeMemoryBarriers::VisitBoundCheck(GraphVisitor *v, Inst *inst)
215 {
216     static_cast<OptimizeMemoryBarriers *>(v)->CheckTwoInputs(inst->GetInput(0).GetInst(), inst->GetInput(1).GetInst());
217 }
218 
ApplyGraph()219 void OptimizeMemoryBarriers::ApplyGraph()
220 {
221     barriers_insts_.clear();
222     for (auto bb : GetGraph()->GetBlocksRPO()) {
223         for (auto inst : bb->Insts()) {
224             if (inst->GetFlag(inst_flags::MEM_BARRIER)) {
225                 barriers_insts_.push_back(inst);
226             }
227             this->VisitInstruction(inst);
228         }
229         this->MergeBarriers();
230     }
231 }
232 
RunImpl()233 bool OptimizeMemoryBarriers::RunImpl()
234 {
235     ApplyGraph();
236     return IsApplied();
237 }
238 
239 }  // namespace panda::compiler
240