xref: /aosp_15_r20/art/compiler/optimizing/scheduler_arm64.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "scheduler_arm64.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "code_generator_utils.h"
20*795d594fSAndroid Build Coastguard Worker #include "mirror/array-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
24*795d594fSAndroid Build Coastguard Worker namespace arm64 {
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64MemoryLoadLatency = 5;
27*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64MemoryStoreLatency = 3;
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64CallInternalLatency = 10;
30*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64CallLatency = 5;
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker // AArch64 instruction latency.
33*795d594fSAndroid Build Coastguard Worker // We currently assume that all arm64 CPUs share the same instruction latency list.
34*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64IntegerOpLatency = 2;
35*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64FloatingPointOpLatency = 5;
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64DataProcWithShifterOpLatency = 3;
38*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64DivDoubleLatency = 30;
39*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64DivFloatLatency = 15;
40*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64DivIntegerLatency = 5;
41*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64LoadStringInternalLatency = 7;
42*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64MulFloatingPointLatency = 6;
43*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64MulIntegerLatency = 6;
44*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64TypeConversionFloatingPointIntegerLatency = 5;
45*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64BranchLatency = kArm64IntegerOpLatency;
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDFloatingPointOpLatency = 10;
48*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDIntegerOpLatency = 6;
49*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDMemoryLoadLatency = 10;
50*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDMemoryStoreLatency = 6;
51*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDMulFloatingPointLatency = 12;
52*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDMulIntegerLatency = 12;
53*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDReplicateOpLatency = 16;
54*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDDivDoubleLatency = 60;
55*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDDivFloatLatency = 30;
56*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArm64SIMDTypeConversionInt2FPLatency = 10;
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker class SchedulingLatencyVisitorARM64 final : public SchedulingLatencyVisitor {
59*795d594fSAndroid Build Coastguard Worker  public:
60*795d594fSAndroid Build Coastguard Worker   // Default visitor for instructions not handled specifically below.
VisitInstruction(HInstruction *)61*795d594fSAndroid Build Coastguard Worker   void VisitInstruction([[maybe_unused]] HInstruction*) override {
62*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64IntegerOpLatency;
63*795d594fSAndroid Build Coastguard Worker   }
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker // We add a second unused parameter to be able to use this macro like the others
66*795d594fSAndroid Build Coastguard Worker // defined in `nodes.h`.
67*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_SCHEDULED_COMMON_INSTRUCTION(M)     \
68*795d594fSAndroid Build Coastguard Worker   M(ArrayGet             , unused)                   \
69*795d594fSAndroid Build Coastguard Worker   M(ArrayLength          , unused)                   \
70*795d594fSAndroid Build Coastguard Worker   M(ArraySet             , unused)                   \
71*795d594fSAndroid Build Coastguard Worker   M(BoundsCheck          , unused)                   \
72*795d594fSAndroid Build Coastguard Worker   M(Div                  , unused)                   \
73*795d594fSAndroid Build Coastguard Worker   M(InstanceFieldGet     , unused)                   \
74*795d594fSAndroid Build Coastguard Worker   M(InstanceOf           , unused)                   \
75*795d594fSAndroid Build Coastguard Worker   M(LoadString           , unused)                   \
76*795d594fSAndroid Build Coastguard Worker   M(Mul                  , unused)                   \
77*795d594fSAndroid Build Coastguard Worker   M(NewArray             , unused)                   \
78*795d594fSAndroid Build Coastguard Worker   M(NewInstance          , unused)                   \
79*795d594fSAndroid Build Coastguard Worker   M(Rem                  , unused)                   \
80*795d594fSAndroid Build Coastguard Worker   M(StaticFieldGet       , unused)                   \
81*795d594fSAndroid Build Coastguard Worker   M(SuspendCheck         , unused)                   \
82*795d594fSAndroid Build Coastguard Worker   M(TypeConversion       , unused)                   \
83*795d594fSAndroid Build Coastguard Worker   M(VecReplicateScalar   , unused)                   \
84*795d594fSAndroid Build Coastguard Worker   M(VecExtractScalar     , unused)                   \
85*795d594fSAndroid Build Coastguard Worker   M(VecReduce            , unused)                   \
86*795d594fSAndroid Build Coastguard Worker   M(VecCnv               , unused)                   \
87*795d594fSAndroid Build Coastguard Worker   M(VecNeg               , unused)                   \
88*795d594fSAndroid Build Coastguard Worker   M(VecAbs               , unused)                   \
89*795d594fSAndroid Build Coastguard Worker   M(VecNot               , unused)                   \
90*795d594fSAndroid Build Coastguard Worker   M(VecAdd               , unused)                   \
91*795d594fSAndroid Build Coastguard Worker   M(VecHalvingAdd        , unused)                   \
92*795d594fSAndroid Build Coastguard Worker   M(VecSub               , unused)                   \
93*795d594fSAndroid Build Coastguard Worker   M(VecMul               , unused)                   \
94*795d594fSAndroid Build Coastguard Worker   M(VecDiv               , unused)                   \
95*795d594fSAndroid Build Coastguard Worker   M(VecMin               , unused)                   \
96*795d594fSAndroid Build Coastguard Worker   M(VecMax               , unused)                   \
97*795d594fSAndroid Build Coastguard Worker   M(VecAnd               , unused)                   \
98*795d594fSAndroid Build Coastguard Worker   M(VecAndNot            , unused)                   \
99*795d594fSAndroid Build Coastguard Worker   M(VecOr                , unused)                   \
100*795d594fSAndroid Build Coastguard Worker   M(VecXor               , unused)                   \
101*795d594fSAndroid Build Coastguard Worker   M(VecShl               , unused)                   \
102*795d594fSAndroid Build Coastguard Worker   M(VecShr               , unused)                   \
103*795d594fSAndroid Build Coastguard Worker   M(VecUShr              , unused)                   \
104*795d594fSAndroid Build Coastguard Worker   M(VecSetScalars        , unused)                   \
105*795d594fSAndroid Build Coastguard Worker   M(VecMultiplyAccumulate, unused)                   \
106*795d594fSAndroid Build Coastguard Worker   M(VecLoad              , unused)                   \
107*795d594fSAndroid Build Coastguard Worker   M(VecStore             , unused)
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_SCHEDULED_ABSTRACT_INSTRUCTION(M)   \
110*795d594fSAndroid Build Coastguard Worker   M(BinaryOperation      , unused)                   \
111*795d594fSAndroid Build Coastguard Worker   M(Invoke               , unused)
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(M) \
114*795d594fSAndroid Build Coastguard Worker   M(BitwiseNegatedRight, unused)                 \
115*795d594fSAndroid Build Coastguard Worker   M(MultiplyAccumulate, unused)                  \
116*795d594fSAndroid Build Coastguard Worker   M(IntermediateAddress, unused)                 \
117*795d594fSAndroid Build Coastguard Worker   M(IntermediateAddressIndex, unused)            \
118*795d594fSAndroid Build Coastguard Worker   M(DataProcWithShifterOp, unused)
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(type, unused)  \
121*795d594fSAndroid Build Coastguard Worker   void Visit##type(H##type* instruction) override;
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker   FOR_EACH_SCHEDULED_COMMON_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
124*795d594fSAndroid Build Coastguard Worker   FOR_EACH_SCHEDULED_ABSTRACT_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
125*795d594fSAndroid Build Coastguard Worker   FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
126*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_ARM64(DECLARE_VISIT_INSTRUCTION)
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker  private:
131*795d594fSAndroid Build Coastguard Worker   void HandleSimpleArithmeticSIMD(HVecOperation *instr);
132*795d594fSAndroid Build Coastguard Worker   void HandleVecAddress(HVecMemoryOperation* instruction, size_t size);
133*795d594fSAndroid Build Coastguard Worker };
134*795d594fSAndroid Build Coastguard Worker 
VisitBinaryOperation(HBinaryOperation * instr)135*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitBinaryOperation(HBinaryOperation* instr) {
136*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = DataType::IsFloatingPointType(instr->GetResultType())
137*795d594fSAndroid Build Coastguard Worker       ? kArm64FloatingPointOpLatency
138*795d594fSAndroid Build Coastguard Worker       : kArm64IntegerOpLatency;
139*795d594fSAndroid Build Coastguard Worker }
140*795d594fSAndroid Build Coastguard Worker 
VisitBitwiseNegatedRight(HBitwiseNegatedRight *)141*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitBitwiseNegatedRight(
142*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HBitwiseNegatedRight*) {
143*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64IntegerOpLatency;
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker 
VisitDataProcWithShifterOp(HDataProcWithShifterOp *)146*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitDataProcWithShifterOp(
147*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HDataProcWithShifterOp*) {
148*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64DataProcWithShifterOpLatency;
149*795d594fSAndroid Build Coastguard Worker }
150*795d594fSAndroid Build Coastguard Worker 
VisitIntermediateAddress(HIntermediateAddress *)151*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitIntermediateAddress(
152*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HIntermediateAddress*) {
153*795d594fSAndroid Build Coastguard Worker   // Although the code generated is a simple `add` instruction, we found through empirical results
154*795d594fSAndroid Build Coastguard Worker   // that spacing it from its use in memory accesses was beneficial.
155*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64IntegerOpLatency + 2;
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker 
VisitIntermediateAddressIndex(HIntermediateAddressIndex * instr)158*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitIntermediateAddressIndex(
159*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HIntermediateAddressIndex* instr) {
160*795d594fSAndroid Build Coastguard Worker   // Although the code generated is a simple `add` instruction, we found through empirical results
161*795d594fSAndroid Build Coastguard Worker   // that spacing it from its use in memory accesses was beneficial.
162*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64DataProcWithShifterOpLatency + 2;
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker 
VisitMultiplyAccumulate(HMultiplyAccumulate *)165*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitMultiplyAccumulate([[maybe_unused]] HMultiplyAccumulate*) {
166*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MulIntegerLatency;
167*795d594fSAndroid Build Coastguard Worker }
168*795d594fSAndroid Build Coastguard Worker 
VisitArrayGet(HArrayGet * instruction)169*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitArrayGet(HArrayGet* instruction) {
170*795d594fSAndroid Build Coastguard Worker   if (!instruction->GetArray()->IsIntermediateAddress()) {
171*795d594fSAndroid Build Coastguard Worker     // Take the intermediate address computation into account.
172*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArm64IntegerOpLatency;
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MemoryLoadLatency;
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker 
VisitArrayLength(HArrayLength *)177*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitArrayLength([[maybe_unused]] HArrayLength*) {
178*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MemoryLoadLatency;
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker 
VisitArraySet(HArraySet *)181*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitArraySet([[maybe_unused]] HArraySet*) {
182*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MemoryStoreLatency;
183*795d594fSAndroid Build Coastguard Worker }
184*795d594fSAndroid Build Coastguard Worker 
VisitBoundsCheck(HBoundsCheck *)185*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitBoundsCheck([[maybe_unused]] HBoundsCheck*) {
186*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArm64IntegerOpLatency;
187*795d594fSAndroid Build Coastguard Worker   // Users do not use any data results.
188*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = 0;
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker 
VisitDiv(HDiv * instr)191*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitDiv(HDiv* instr) {
192*795d594fSAndroid Build Coastguard Worker   DataType::Type type = instr->GetResultType();
193*795d594fSAndroid Build Coastguard Worker   switch (type) {
194*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
195*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArm64DivFloatLatency;
196*795d594fSAndroid Build Coastguard Worker       break;
197*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
198*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArm64DivDoubleLatency;
199*795d594fSAndroid Build Coastguard Worker       break;
200*795d594fSAndroid Build Coastguard Worker     default:
201*795d594fSAndroid Build Coastguard Worker       // Follow the code path used by code generation.
202*795d594fSAndroid Build Coastguard Worker       if (instr->GetRight()->IsConstant()) {
203*795d594fSAndroid Build Coastguard Worker         int64_t imm = Int64FromConstant(instr->GetRight()->AsConstant());
204*795d594fSAndroid Build Coastguard Worker         if (imm == 0) {
205*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 0;
206*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = 0;
207*795d594fSAndroid Build Coastguard Worker         } else if (imm == 1 || imm == -1) {
208*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 0;
209*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArm64IntegerOpLatency;
210*795d594fSAndroid Build Coastguard Worker         } else if (IsPowerOfTwo(AbsOrMin(imm))) {
211*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 4 * kArm64IntegerOpLatency;
212*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArm64IntegerOpLatency;
213*795d594fSAndroid Build Coastguard Worker         } else {
214*795d594fSAndroid Build Coastguard Worker           DCHECK(imm <= -2 || imm >= 2);
215*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 4 * kArm64IntegerOpLatency;
216*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArm64MulIntegerLatency;
217*795d594fSAndroid Build Coastguard Worker         }
218*795d594fSAndroid Build Coastguard Worker       } else {
219*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArm64DivIntegerLatency;
220*795d594fSAndroid Build Coastguard Worker       }
221*795d594fSAndroid Build Coastguard Worker       break;
222*795d594fSAndroid Build Coastguard Worker   }
223*795d594fSAndroid Build Coastguard Worker }
224*795d594fSAndroid Build Coastguard Worker 
VisitInstanceFieldGet(HInstanceFieldGet *)225*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitInstanceFieldGet([[maybe_unused]] HInstanceFieldGet*) {
226*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MemoryLoadLatency;
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker 
VisitInstanceOf(HInstanceOf *)229*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitInstanceOf([[maybe_unused]] HInstanceOf*) {
230*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArm64CallInternalLatency;
231*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64IntegerOpLatency;
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker 
VisitInvoke(HInvoke *)234*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitInvoke([[maybe_unused]] HInvoke*) {
235*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArm64CallInternalLatency;
236*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64CallLatency;
237*795d594fSAndroid Build Coastguard Worker }
238*795d594fSAndroid Build Coastguard Worker 
VisitLoadString(HLoadString *)239*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitLoadString([[maybe_unused]] HLoadString*) {
240*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArm64LoadStringInternalLatency;
241*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MemoryLoadLatency;
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker 
VisitMul(HMul * instr)244*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitMul(HMul* instr) {
245*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = DataType::IsFloatingPointType(instr->GetResultType())
246*795d594fSAndroid Build Coastguard Worker       ? kArm64MulFloatingPointLatency
247*795d594fSAndroid Build Coastguard Worker       : kArm64MulIntegerLatency;
248*795d594fSAndroid Build Coastguard Worker }
249*795d594fSAndroid Build Coastguard Worker 
VisitNewArray(HNewArray *)250*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitNewArray([[maybe_unused]] HNewArray*) {
251*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArm64IntegerOpLatency + kArm64CallInternalLatency;
252*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64CallLatency;
253*795d594fSAndroid Build Coastguard Worker }
254*795d594fSAndroid Build Coastguard Worker 
VisitNewInstance(HNewInstance * instruction)255*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitNewInstance(HNewInstance* instruction) {
256*795d594fSAndroid Build Coastguard Worker   if (instruction->IsStringAlloc()) {
257*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = 2 + kArm64MemoryLoadLatency + kArm64CallInternalLatency;
258*795d594fSAndroid Build Coastguard Worker   } else {
259*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArm64CallInternalLatency;
260*795d594fSAndroid Build Coastguard Worker   }
261*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64CallLatency;
262*795d594fSAndroid Build Coastguard Worker }
263*795d594fSAndroid Build Coastguard Worker 
VisitRem(HRem * instruction)264*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitRem(HRem* instruction) {
265*795d594fSAndroid Build Coastguard Worker   if (DataType::IsFloatingPointType(instruction->GetResultType())) {
266*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArm64CallInternalLatency;
267*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64CallLatency;
268*795d594fSAndroid Build Coastguard Worker   } else {
269*795d594fSAndroid Build Coastguard Worker     // Follow the code path used by code generation.
270*795d594fSAndroid Build Coastguard Worker     if (instruction->GetRight()->IsConstant()) {
271*795d594fSAndroid Build Coastguard Worker       int64_t imm = Int64FromConstant(instruction->GetRight()->AsConstant());
272*795d594fSAndroid Build Coastguard Worker       if (imm == 0) {
273*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = 0;
274*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = 0;
275*795d594fSAndroid Build Coastguard Worker       } else if (imm == 1 || imm == -1) {
276*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = 0;
277*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArm64IntegerOpLatency;
278*795d594fSAndroid Build Coastguard Worker       } else if (IsPowerOfTwo(AbsOrMin(imm))) {
279*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = 4 * kArm64IntegerOpLatency;
280*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArm64IntegerOpLatency;
281*795d594fSAndroid Build Coastguard Worker       } else {
282*795d594fSAndroid Build Coastguard Worker         DCHECK(imm <= -2 || imm >= 2);
283*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = 4 * kArm64IntegerOpLatency;
284*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArm64MulIntegerLatency;
285*795d594fSAndroid Build Coastguard Worker       }
286*795d594fSAndroid Build Coastguard Worker     } else {
287*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArm64DivIntegerLatency;
288*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArm64MulIntegerLatency;
289*795d594fSAndroid Build Coastguard Worker     }
290*795d594fSAndroid Build Coastguard Worker   }
291*795d594fSAndroid Build Coastguard Worker }
292*795d594fSAndroid Build Coastguard Worker 
VisitStaticFieldGet(HStaticFieldGet *)293*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitStaticFieldGet([[maybe_unused]] HStaticFieldGet*) {
294*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64MemoryLoadLatency;
295*795d594fSAndroid Build Coastguard Worker }
296*795d594fSAndroid Build Coastguard Worker 
VisitSuspendCheck(HSuspendCheck * instruction)297*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitSuspendCheck(HSuspendCheck* instruction) {
298*795d594fSAndroid Build Coastguard Worker   HBasicBlock* block = instruction->GetBlock();
299*795d594fSAndroid Build Coastguard Worker   DCHECK_IMPLIES(block->GetLoopInformation() == nullptr,
300*795d594fSAndroid Build Coastguard Worker                  block->IsEntryBlock() && instruction->GetNext()->IsGoto());
301*795d594fSAndroid Build Coastguard Worker   // Users do not use any data results.
302*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = 0;
303*795d594fSAndroid Build Coastguard Worker }
304*795d594fSAndroid Build Coastguard Worker 
VisitTypeConversion(HTypeConversion * instr)305*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitTypeConversion(HTypeConversion* instr) {
306*795d594fSAndroid Build Coastguard Worker   if (DataType::IsFloatingPointType(instr->GetResultType()) ||
307*795d594fSAndroid Build Coastguard Worker       DataType::IsFloatingPointType(instr->GetInputType())) {
308*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64TypeConversionFloatingPointIntegerLatency;
309*795d594fSAndroid Build Coastguard Worker   } else {
310*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64IntegerOpLatency;
311*795d594fSAndroid Build Coastguard Worker   }
312*795d594fSAndroid Build Coastguard Worker }
313*795d594fSAndroid Build Coastguard Worker 
HandleSimpleArithmeticSIMD(HVecOperation * instr)314*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::HandleSimpleArithmeticSIMD(HVecOperation *instr) {
315*795d594fSAndroid Build Coastguard Worker   if (DataType::IsFloatingPointType(instr->GetPackedType())) {
316*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDFloatingPointOpLatency;
317*795d594fSAndroid Build Coastguard Worker   } else {
318*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDIntegerOpLatency;
319*795d594fSAndroid Build Coastguard Worker   }
320*795d594fSAndroid Build Coastguard Worker }
321*795d594fSAndroid Build Coastguard Worker 
VisitVecReplicateScalar(HVecReplicateScalar * instr)322*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecReplicateScalar(
323*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HVecReplicateScalar* instr) {
324*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDReplicateOpLatency;
325*795d594fSAndroid Build Coastguard Worker }
326*795d594fSAndroid Build Coastguard Worker 
VisitVecExtractScalar(HVecExtractScalar * instr)327*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecExtractScalar(HVecExtractScalar* instr) {
328*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
329*795d594fSAndroid Build Coastguard Worker }
330*795d594fSAndroid Build Coastguard Worker 
VisitVecReduce(HVecReduce * instr)331*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecReduce(HVecReduce* instr) {
332*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
333*795d594fSAndroid Build Coastguard Worker }
334*795d594fSAndroid Build Coastguard Worker 
VisitVecCnv(HVecCnv * instr)335*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecCnv([[maybe_unused]] HVecCnv* instr) {
336*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDTypeConversionInt2FPLatency;
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker 
VisitVecNeg(HVecNeg * instr)339*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecNeg(HVecNeg* instr) {
340*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
341*795d594fSAndroid Build Coastguard Worker }
342*795d594fSAndroid Build Coastguard Worker 
VisitVecAbs(HVecAbs * instr)343*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecAbs(HVecAbs* instr) {
344*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
345*795d594fSAndroid Build Coastguard Worker }
346*795d594fSAndroid Build Coastguard Worker 
VisitVecNot(HVecNot * instr)347*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecNot(HVecNot* instr) {
348*795d594fSAndroid Build Coastguard Worker   if (instr->GetPackedType() == DataType::Type::kBool) {
349*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArm64SIMDIntegerOpLatency;
350*795d594fSAndroid Build Coastguard Worker   }
351*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDIntegerOpLatency;
352*795d594fSAndroid Build Coastguard Worker }
353*795d594fSAndroid Build Coastguard Worker 
VisitVecAdd(HVecAdd * instr)354*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecAdd(HVecAdd* instr) {
355*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
356*795d594fSAndroid Build Coastguard Worker }
357*795d594fSAndroid Build Coastguard Worker 
VisitVecHalvingAdd(HVecHalvingAdd * instr)358*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecHalvingAdd(HVecHalvingAdd* instr) {
359*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
360*795d594fSAndroid Build Coastguard Worker }
361*795d594fSAndroid Build Coastguard Worker 
VisitVecSub(HVecSub * instr)362*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecSub(HVecSub* instr) {
363*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
364*795d594fSAndroid Build Coastguard Worker }
365*795d594fSAndroid Build Coastguard Worker 
VisitVecMul(HVecMul * instr)366*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecMul(HVecMul* instr) {
367*795d594fSAndroid Build Coastguard Worker   if (DataType::IsFloatingPointType(instr->GetPackedType())) {
368*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDMulFloatingPointLatency;
369*795d594fSAndroid Build Coastguard Worker   } else {
370*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDMulIntegerLatency;
371*795d594fSAndroid Build Coastguard Worker   }
372*795d594fSAndroid Build Coastguard Worker }
373*795d594fSAndroid Build Coastguard Worker 
VisitVecDiv(HVecDiv * instr)374*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecDiv(HVecDiv* instr) {
375*795d594fSAndroid Build Coastguard Worker   if (instr->GetPackedType() == DataType::Type::kFloat32) {
376*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDDivFloatLatency;
377*795d594fSAndroid Build Coastguard Worker   } else {
378*795d594fSAndroid Build Coastguard Worker     DCHECK(instr->GetPackedType() == DataType::Type::kFloat64);
379*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDDivDoubleLatency;
380*795d594fSAndroid Build Coastguard Worker   }
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker 
VisitVecMin(HVecMin * instr)383*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecMin(HVecMin* instr) {
384*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
385*795d594fSAndroid Build Coastguard Worker }
386*795d594fSAndroid Build Coastguard Worker 
VisitVecMax(HVecMax * instr)387*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecMax(HVecMax* instr) {
388*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker 
VisitVecAnd(HVecAnd * instr)391*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecAnd([[maybe_unused]] HVecAnd* instr) {
392*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDIntegerOpLatency;
393*795d594fSAndroid Build Coastguard Worker }
394*795d594fSAndroid Build Coastguard Worker 
VisitVecAndNot(HVecAndNot * instr)395*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecAndNot([[maybe_unused]] HVecAndNot* instr) {
396*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDIntegerOpLatency;
397*795d594fSAndroid Build Coastguard Worker }
398*795d594fSAndroid Build Coastguard Worker 
VisitVecOr(HVecOr * instr)399*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecOr([[maybe_unused]] HVecOr* instr) {
400*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDIntegerOpLatency;
401*795d594fSAndroid Build Coastguard Worker }
402*795d594fSAndroid Build Coastguard Worker 
VisitVecXor(HVecXor * instr)403*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecXor([[maybe_unused]] HVecXor* instr) {
404*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDIntegerOpLatency;
405*795d594fSAndroid Build Coastguard Worker }
406*795d594fSAndroid Build Coastguard Worker 
VisitVecShl(HVecShl * instr)407*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecShl(HVecShl* instr) {
408*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
409*795d594fSAndroid Build Coastguard Worker }
410*795d594fSAndroid Build Coastguard Worker 
VisitVecShr(HVecShr * instr)411*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecShr(HVecShr* instr) {
412*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker 
VisitVecUShr(HVecUShr * instr)415*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecUShr(HVecUShr* instr) {
416*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
417*795d594fSAndroid Build Coastguard Worker }
418*795d594fSAndroid Build Coastguard Worker 
VisitVecSetScalars(HVecSetScalars * instr)419*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecSetScalars(HVecSetScalars* instr) {
420*795d594fSAndroid Build Coastguard Worker   HandleSimpleArithmeticSIMD(instr);
421*795d594fSAndroid Build Coastguard Worker }
422*795d594fSAndroid Build Coastguard Worker 
VisitVecMultiplyAccumulate(HVecMultiplyAccumulate * instr)423*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecMultiplyAccumulate(
424*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HVecMultiplyAccumulate* instr) {
425*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDMulIntegerLatency;
426*795d594fSAndroid Build Coastguard Worker }
427*795d594fSAndroid Build Coastguard Worker 
HandleVecAddress(HVecMemoryOperation * instruction,size_t size)428*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::HandleVecAddress(HVecMemoryOperation* instruction,
429*795d594fSAndroid Build Coastguard Worker                                                      [[maybe_unused]] size_t size) {
430*795d594fSAndroid Build Coastguard Worker   HInstruction* index = instruction->InputAt(1);
431*795d594fSAndroid Build Coastguard Worker   if (!index->IsConstant()) {
432*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += kArm64DataProcWithShifterOpLatency;
433*795d594fSAndroid Build Coastguard Worker   }
434*795d594fSAndroid Build Coastguard Worker }
435*795d594fSAndroid Build Coastguard Worker 
VisitVecLoad(HVecLoad * instr)436*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecLoad(HVecLoad* instr) {
437*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = 0;
438*795d594fSAndroid Build Coastguard Worker   size_t size = DataType::Size(instr->GetPackedType());
439*795d594fSAndroid Build Coastguard Worker 
440*795d594fSAndroid Build Coastguard Worker   if (instr->GetPackedType() == DataType::Type::kUint16
441*795d594fSAndroid Build Coastguard Worker       && mirror::kUseStringCompression
442*795d594fSAndroid Build Coastguard Worker       && instr->IsStringCharAt()) {
443*795d594fSAndroid Build Coastguard Worker     // Set latencies for the uncompressed case.
444*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += kArm64MemoryLoadLatency + kArm64BranchLatency;
445*795d594fSAndroid Build Coastguard Worker     HandleVecAddress(instr, size);
446*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDMemoryLoadLatency;
447*795d594fSAndroid Build Coastguard Worker   } else {
448*795d594fSAndroid Build Coastguard Worker     HandleVecAddress(instr, size);
449*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArm64SIMDMemoryLoadLatency;
450*795d594fSAndroid Build Coastguard Worker   }
451*795d594fSAndroid Build Coastguard Worker }
452*795d594fSAndroid Build Coastguard Worker 
VisitVecStore(HVecStore * instr)453*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM64::VisitVecStore(HVecStore* instr) {
454*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = 0;
455*795d594fSAndroid Build Coastguard Worker   size_t size = DataType::Size(instr->GetPackedType());
456*795d594fSAndroid Build Coastguard Worker   HandleVecAddress(instr, size);
457*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArm64SIMDMemoryStoreLatency;
458*795d594fSAndroid Build Coastguard Worker }
459*795d594fSAndroid Build Coastguard Worker 
IsSchedulable(const HInstruction * instruction) const460*795d594fSAndroid Build Coastguard Worker bool HSchedulerARM64::IsSchedulable(const HInstruction* instruction) const {
461*795d594fSAndroid Build Coastguard Worker   switch (instruction->GetKind()) {
462*795d594fSAndroid Build Coastguard Worker #define SCHEDULABLE_CASE(type, unused)       \
463*795d594fSAndroid Build Coastguard Worker     case HInstruction::InstructionKind::k##type:  \
464*795d594fSAndroid Build Coastguard Worker       return true;
465*795d594fSAndroid Build Coastguard Worker     FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(SCHEDULABLE_CASE)
466*795d594fSAndroid Build Coastguard Worker     FOR_EACH_CONCRETE_INSTRUCTION_ARM64(SCHEDULABLE_CASE)
467*795d594fSAndroid Build Coastguard Worker     FOR_EACH_SCHEDULED_COMMON_INSTRUCTION(SCHEDULABLE_CASE)
468*795d594fSAndroid Build Coastguard Worker #undef SCHEDULABLE_CASE
469*795d594fSAndroid Build Coastguard Worker 
470*795d594fSAndroid Build Coastguard Worker     default:
471*795d594fSAndroid Build Coastguard Worker       return HScheduler::IsSchedulable(instruction);
472*795d594fSAndroid Build Coastguard Worker   }
473*795d594fSAndroid Build Coastguard Worker }
474*795d594fSAndroid Build Coastguard Worker 
475*795d594fSAndroid Build Coastguard Worker std::pair<SchedulingGraph, ScopedArenaVector<SchedulingNode*>>
BuildSchedulingGraph(HBasicBlock * block,ScopedArenaAllocator * allocator,const HeapLocationCollector * heap_location_collector)476*795d594fSAndroid Build Coastguard Worker HSchedulerARM64::BuildSchedulingGraph(
477*795d594fSAndroid Build Coastguard Worker     HBasicBlock* block,
478*795d594fSAndroid Build Coastguard Worker     ScopedArenaAllocator* allocator,
479*795d594fSAndroid Build Coastguard Worker     const HeapLocationCollector* heap_location_collector) {
480*795d594fSAndroid Build Coastguard Worker   SchedulingLatencyVisitorARM64 latency_visitor;
481*795d594fSAndroid Build Coastguard Worker   return HScheduler::BuildSchedulingGraph(
482*795d594fSAndroid Build Coastguard Worker       block, allocator, heap_location_collector, &latency_visitor);
483*795d594fSAndroid Build Coastguard Worker }
484*795d594fSAndroid Build Coastguard Worker 
485*795d594fSAndroid Build Coastguard Worker }  // namespace arm64
486*795d594fSAndroid Build Coastguard Worker }  // namespace art
487