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