xref: /aosp_15_r20/art/compiler/optimizing/scheduler_arm.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2017 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_arm.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include "arch/arm/instruction_set_features_arm.h"
20*795d594fSAndroid Build Coastguard Worker #include "code_generator_arm_vixl.h"
21*795d594fSAndroid Build Coastguard Worker #include "code_generator_utils.h"
22*795d594fSAndroid Build Coastguard Worker #include "common_arm.h"
23*795d594fSAndroid Build Coastguard Worker #include "heap_poisoning.h"
24*795d594fSAndroid Build Coastguard Worker #include "mirror/array-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
28*795d594fSAndroid Build Coastguard Worker namespace arm {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker using helpers::Int32ConstantFrom;
31*795d594fSAndroid Build Coastguard Worker using helpers::Uint64ConstantFrom;
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker // AArch32 instruction latencies.
34*795d594fSAndroid Build Coastguard Worker // We currently assume that all ARM CPUs share the same instruction latency list.
35*795d594fSAndroid Build Coastguard Worker // The following latencies were tuned based on performance experiments and
36*795d594fSAndroid Build Coastguard Worker // automatic tuning using differential evolution approach on various benchmarks.
37*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmIntegerOpLatency = 2;
38*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmFloatingPointOpLatency = 11;
39*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmDataProcWithShifterOpLatency = 4;
40*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmMulIntegerLatency = 6;
41*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmMulFloatingPointLatency = 11;
42*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmDivIntegerLatency = 10;
43*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmDivFloatLatency = 20;
44*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmDivDoubleLatency = 25;
45*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmTypeConversionFloatingPointIntegerLatency = 11;
46*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmMemoryLoadLatency = 9;
47*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmMemoryStoreLatency = 9;
48*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmMemoryBarrierLatency = 6;
49*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmBranchLatency = 4;
50*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmCallLatency = 5;
51*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmCallInternalLatency = 29;
52*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmLoadStringInternalLatency = 10;
53*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmNopLatency = 2;
54*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmLoadWithBakerReadBarrierLatency = 18;
55*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kArmRuntimeTypeCheckLatency = 46;
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker class SchedulingLatencyVisitorARM final : public SchedulingLatencyVisitor {
58*795d594fSAndroid Build Coastguard Worker  public:
SchedulingLatencyVisitorARM(CodeGenerator * codegen)59*795d594fSAndroid Build Coastguard Worker   explicit SchedulingLatencyVisitorARM(CodeGenerator* codegen)
60*795d594fSAndroid Build Coastguard Worker       : codegen_(down_cast<CodeGeneratorARMVIXL*>(codegen)) {}
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker   // Default visitor for instructions not handled specifically below.
VisitInstruction(HInstruction *)63*795d594fSAndroid Build Coastguard Worker   void VisitInstruction([[maybe_unused]] HInstruction*) override {
64*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
65*795d594fSAndroid Build Coastguard Worker   }
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker // We add a second unused parameter to be able to use this macro like the others
68*795d594fSAndroid Build Coastguard Worker // defined in `nodes.h`.
69*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_SCHEDULED_ARM_INSTRUCTION(M) \
70*795d594fSAndroid Build Coastguard Worker   M(ArrayGet, unused)                         \
71*795d594fSAndroid Build Coastguard Worker   M(ArrayLength, unused)                      \
72*795d594fSAndroid Build Coastguard Worker   M(ArraySet, unused)                         \
73*795d594fSAndroid Build Coastguard Worker   M(Add, unused)                              \
74*795d594fSAndroid Build Coastguard Worker   M(Sub, unused)                              \
75*795d594fSAndroid Build Coastguard Worker   M(And, unused)                              \
76*795d594fSAndroid Build Coastguard Worker   M(Or, unused)                               \
77*795d594fSAndroid Build Coastguard Worker   M(Ror, unused)                              \
78*795d594fSAndroid Build Coastguard Worker   M(Xor, unused)                              \
79*795d594fSAndroid Build Coastguard Worker   M(Shl, unused)                              \
80*795d594fSAndroid Build Coastguard Worker   M(Shr, unused)                              \
81*795d594fSAndroid Build Coastguard Worker   M(UShr, unused)                             \
82*795d594fSAndroid Build Coastguard Worker   M(Mul, unused)                              \
83*795d594fSAndroid Build Coastguard Worker   M(Div, unused)                              \
84*795d594fSAndroid Build Coastguard Worker   M(Condition, unused)                        \
85*795d594fSAndroid Build Coastguard Worker   M(Compare, unused)                          \
86*795d594fSAndroid Build Coastguard Worker   M(BoundsCheck, unused)                      \
87*795d594fSAndroid Build Coastguard Worker   M(InstanceFieldGet, unused)                 \
88*795d594fSAndroid Build Coastguard Worker   M(InstanceFieldSet, unused)                 \
89*795d594fSAndroid Build Coastguard Worker   M(InstanceOf, unused)                       \
90*795d594fSAndroid Build Coastguard Worker   M(Invoke, unused)                           \
91*795d594fSAndroid Build Coastguard Worker   M(LoadString, unused)                       \
92*795d594fSAndroid Build Coastguard Worker   M(NewArray, unused)                         \
93*795d594fSAndroid Build Coastguard Worker   M(NewInstance, unused)                      \
94*795d594fSAndroid Build Coastguard Worker   M(Rem, unused)                              \
95*795d594fSAndroid Build Coastguard Worker   M(StaticFieldGet, unused)                   \
96*795d594fSAndroid Build Coastguard Worker   M(StaticFieldSet, unused)                   \
97*795d594fSAndroid Build Coastguard Worker   M(SuspendCheck, unused)                     \
98*795d594fSAndroid Build Coastguard Worker   M(TypeConversion, unused)
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(M) \
101*795d594fSAndroid Build Coastguard Worker   M(BitwiseNegatedRight, unused)                 \
102*795d594fSAndroid Build Coastguard Worker   M(MultiplyAccumulate, unused)                  \
103*795d594fSAndroid Build Coastguard Worker   M(IntermediateAddress, unused)                 \
104*795d594fSAndroid Build Coastguard Worker   M(IntermediateAddressIndex, unused)            \
105*795d594fSAndroid Build Coastguard Worker   M(DataProcWithShifterOp, unused)
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(type, unused)  \
108*795d594fSAndroid Build Coastguard Worker   void Visit##type(H##type* instruction) override;
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker   FOR_EACH_SCHEDULED_ARM_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
111*795d594fSAndroid Build Coastguard Worker   FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
112*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_ARM(DECLARE_VISIT_INSTRUCTION)
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker  private:
117*795d594fSAndroid Build Coastguard Worker   bool CanGenerateTest(HCondition* cond);
118*795d594fSAndroid Build Coastguard Worker   void HandleGenerateConditionWithZero(IfCondition cond);
119*795d594fSAndroid Build Coastguard Worker   void HandleGenerateLongTestConstant(HCondition* cond);
120*795d594fSAndroid Build Coastguard Worker   void HandleGenerateLongTest(HCondition* cond);
121*795d594fSAndroid Build Coastguard Worker   void HandleGenerateLongComparesAndJumps();
122*795d594fSAndroid Build Coastguard Worker   void HandleGenerateTest(HCondition* cond);
123*795d594fSAndroid Build Coastguard Worker   void HandleGenerateConditionGeneric(HCondition* cond);
124*795d594fSAndroid Build Coastguard Worker   void HandleGenerateEqualLong(HCondition* cond);
125*795d594fSAndroid Build Coastguard Worker   void HandleGenerateConditionLong(HCondition* cond);
126*795d594fSAndroid Build Coastguard Worker   void HandleGenerateConditionIntegralOrNonPrimitive(HCondition* cond);
127*795d594fSAndroid Build Coastguard Worker   void HandleCondition(HCondition* instr);
128*795d594fSAndroid Build Coastguard Worker   void HandleBinaryOperationLantencies(HBinaryOperation* instr);
129*795d594fSAndroid Build Coastguard Worker   void HandleBitwiseOperationLantencies(HBinaryOperation* instr);
130*795d594fSAndroid Build Coastguard Worker   void HandleShiftLatencies(HBinaryOperation* instr);
131*795d594fSAndroid Build Coastguard Worker   void HandleDivRemConstantIntegralLatencies(int32_t imm);
132*795d594fSAndroid Build Coastguard Worker   void HandleFieldSetLatencies(HInstruction* instruction, const FieldInfo& field_info);
133*795d594fSAndroid Build Coastguard Worker   void HandleFieldGetLatencies(HInstruction* instruction, const FieldInfo& field_info);
134*795d594fSAndroid Build Coastguard Worker   void HandleGenerateDataProcInstruction(bool internal_latency = false);
135*795d594fSAndroid Build Coastguard Worker   void HandleGenerateDataProc(HDataProcWithShifterOp* instruction);
136*795d594fSAndroid Build Coastguard Worker   void HandleGenerateLongDataProc(HDataProcWithShifterOp* instruction);
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   // The latency setting for each HInstruction depends on how CodeGenerator may generate code,
139*795d594fSAndroid Build Coastguard Worker   // latency visitors may query CodeGenerator for such information for accurate latency settings.
140*795d594fSAndroid Build Coastguard Worker   CodeGeneratorARMVIXL* codegen_;
141*795d594fSAndroid Build Coastguard Worker };
142*795d594fSAndroid Build Coastguard Worker 
HandleBinaryOperationLantencies(HBinaryOperation * instr)143*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleBinaryOperationLantencies(HBinaryOperation* instr) {
144*795d594fSAndroid Build Coastguard Worker   switch (instr->GetResultType()) {
145*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
146*795d594fSAndroid Build Coastguard Worker       // HAdd and HSub long operations translate to ADDS+ADC or SUBS+SBC pairs,
147*795d594fSAndroid Build Coastguard Worker       // so a bubble (kArmNopLatency) is added to represent the internal carry flag
148*795d594fSAndroid Build Coastguard Worker       // dependency inside these pairs.
149*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArmIntegerOpLatency + kArmNopLatency;
150*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
151*795d594fSAndroid Build Coastguard Worker       break;
152*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
153*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
154*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmFloatingPointOpLatency;
155*795d594fSAndroid Build Coastguard Worker       break;
156*795d594fSAndroid Build Coastguard Worker     default:
157*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
158*795d594fSAndroid Build Coastguard Worker       break;
159*795d594fSAndroid Build Coastguard Worker   }
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker 
VisitAdd(HAdd * instr)162*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitAdd(HAdd* instr) {
163*795d594fSAndroid Build Coastguard Worker   HandleBinaryOperationLantencies(instr);
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker 
VisitSub(HSub * instr)166*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitSub(HSub* instr) {
167*795d594fSAndroid Build Coastguard Worker   HandleBinaryOperationLantencies(instr);
168*795d594fSAndroid Build Coastguard Worker }
169*795d594fSAndroid Build Coastguard Worker 
VisitMul(HMul * instr)170*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitMul(HMul* instr) {
171*795d594fSAndroid Build Coastguard Worker   switch (instr->GetResultType()) {
172*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
173*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = 3 * kArmMulIntegerLatency;
174*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
175*795d594fSAndroid Build Coastguard Worker       break;
176*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
177*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
178*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMulFloatingPointLatency;
179*795d594fSAndroid Build Coastguard Worker       break;
180*795d594fSAndroid Build Coastguard Worker     default:
181*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMulIntegerLatency;
182*795d594fSAndroid Build Coastguard Worker       break;
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker }
185*795d594fSAndroid Build Coastguard Worker 
HandleBitwiseOperationLantencies(HBinaryOperation * instr)186*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleBitwiseOperationLantencies(HBinaryOperation* instr) {
187*795d594fSAndroid Build Coastguard Worker   switch (instr->GetResultType()) {
188*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
189*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArmIntegerOpLatency;
190*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
191*795d594fSAndroid Build Coastguard Worker       break;
192*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
193*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
194*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmFloatingPointOpLatency;
195*795d594fSAndroid Build Coastguard Worker       break;
196*795d594fSAndroid Build Coastguard Worker     default:
197*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
198*795d594fSAndroid Build Coastguard Worker       break;
199*795d594fSAndroid Build Coastguard Worker   }
200*795d594fSAndroid Build Coastguard Worker }
201*795d594fSAndroid Build Coastguard Worker 
VisitAnd(HAnd * instr)202*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitAnd(HAnd* instr) {
203*795d594fSAndroid Build Coastguard Worker   HandleBitwiseOperationLantencies(instr);
204*795d594fSAndroid Build Coastguard Worker }
205*795d594fSAndroid Build Coastguard Worker 
VisitOr(HOr * instr)206*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitOr(HOr* instr) {
207*795d594fSAndroid Build Coastguard Worker   HandleBitwiseOperationLantencies(instr);
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker 
VisitXor(HXor * instr)210*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitXor(HXor* instr) {
211*795d594fSAndroid Build Coastguard Worker   HandleBitwiseOperationLantencies(instr);
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker 
VisitRor(HRor * instr)214*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitRor(HRor* instr) {
215*795d594fSAndroid Build Coastguard Worker   switch (instr->GetResultType()) {
216*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32:
217*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
218*795d594fSAndroid Build Coastguard Worker       break;
219*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64: {
220*795d594fSAndroid Build Coastguard Worker       // HandleLongRotate
221*795d594fSAndroid Build Coastguard Worker       HInstruction* rhs = instr->GetRight();
222*795d594fSAndroid Build Coastguard Worker       if (rhs->IsConstant()) {
223*795d594fSAndroid Build Coastguard Worker         uint64_t rot = Uint64ConstantFrom(rhs->AsConstant()) & kMaxLongShiftDistance;
224*795d594fSAndroid Build Coastguard Worker         if (rot != 0u) {
225*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 3 * kArmIntegerOpLatency;
226*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmIntegerOpLatency;
227*795d594fSAndroid Build Coastguard Worker         } else {
228*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmIntegerOpLatency;
229*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmIntegerOpLatency;
230*795d594fSAndroid Build Coastguard Worker         }
231*795d594fSAndroid Build Coastguard Worker       } else {
232*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = 9 * kArmIntegerOpLatency + kArmBranchLatency;
233*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmBranchLatency;
234*795d594fSAndroid Build Coastguard Worker       }
235*795d594fSAndroid Build Coastguard Worker       break;
236*795d594fSAndroid Build Coastguard Worker     }
237*795d594fSAndroid Build Coastguard Worker     default:
238*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unexpected operation type " << instr->GetResultType();
239*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
240*795d594fSAndroid Build Coastguard Worker   }
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker 
HandleShiftLatencies(HBinaryOperation * instr)243*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleShiftLatencies(HBinaryOperation* instr) {
244*795d594fSAndroid Build Coastguard Worker   DataType::Type type = instr->GetResultType();
245*795d594fSAndroid Build Coastguard Worker   HInstruction* rhs = instr->GetRight();
246*795d594fSAndroid Build Coastguard Worker   switch (type) {
247*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32:
248*795d594fSAndroid Build Coastguard Worker       if (!rhs->IsConstant()) {
249*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmIntegerOpLatency;
250*795d594fSAndroid Build Coastguard Worker       }
251*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
252*795d594fSAndroid Build Coastguard Worker       break;
253*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
254*795d594fSAndroid Build Coastguard Worker       if (!rhs->IsConstant()) {
255*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = 8 * kArmIntegerOpLatency;
256*795d594fSAndroid Build Coastguard Worker       } else {
257*795d594fSAndroid Build Coastguard Worker         uint32_t shift_value = Int32ConstantFrom(rhs->AsConstant()) & kMaxLongShiftDistance;
258*795d594fSAndroid Build Coastguard Worker         if (shift_value == 1 || shift_value >= 32) {
259*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmIntegerOpLatency;
260*795d594fSAndroid Build Coastguard Worker         } else {
261*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
262*795d594fSAndroid Build Coastguard Worker         }
263*795d594fSAndroid Build Coastguard Worker       }
264*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
265*795d594fSAndroid Build Coastguard Worker       break;
266*795d594fSAndroid Build Coastguard Worker     default:
267*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unexpected operation type " << type;
268*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
269*795d594fSAndroid Build Coastguard Worker   }
270*795d594fSAndroid Build Coastguard Worker }
271*795d594fSAndroid Build Coastguard Worker 
VisitShl(HShl * instr)272*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitShl(HShl* instr) {
273*795d594fSAndroid Build Coastguard Worker   HandleShiftLatencies(instr);
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker 
VisitShr(HShr * instr)276*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitShr(HShr* instr) {
277*795d594fSAndroid Build Coastguard Worker   HandleShiftLatencies(instr);
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker 
VisitUShr(HUShr * instr)280*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitUShr(HUShr* instr) {
281*795d594fSAndroid Build Coastguard Worker   HandleShiftLatencies(instr);
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker 
HandleGenerateConditionWithZero(IfCondition condition)284*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateConditionWithZero(IfCondition condition) {
285*795d594fSAndroid Build Coastguard Worker   switch (condition) {
286*795d594fSAndroid Build Coastguard Worker     case kCondEQ:
287*795d594fSAndroid Build Coastguard Worker     case kCondBE:
288*795d594fSAndroid Build Coastguard Worker     case kCondNE:
289*795d594fSAndroid Build Coastguard Worker     case kCondA:
290*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += kArmIntegerOpLatency;
291*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
292*795d594fSAndroid Build Coastguard Worker       break;
293*795d594fSAndroid Build Coastguard Worker     case kCondGE:
294*795d594fSAndroid Build Coastguard Worker       // Mvn
295*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += kArmIntegerOpLatency;
296*795d594fSAndroid Build Coastguard Worker       FALLTHROUGH_INTENDED;
297*795d594fSAndroid Build Coastguard Worker     case kCondLT:
298*795d594fSAndroid Build Coastguard Worker       // Lsr
299*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
300*795d594fSAndroid Build Coastguard Worker       break;
301*795d594fSAndroid Build Coastguard Worker     case kCondAE:
302*795d594fSAndroid Build Coastguard Worker       // Trivially true.
303*795d594fSAndroid Build Coastguard Worker       // Mov
304*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
305*795d594fSAndroid Build Coastguard Worker       break;
306*795d594fSAndroid Build Coastguard Worker     case kCondB:
307*795d594fSAndroid Build Coastguard Worker       // Trivially false.
308*795d594fSAndroid Build Coastguard Worker       // Mov
309*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
310*795d594fSAndroid Build Coastguard Worker       break;
311*795d594fSAndroid Build Coastguard Worker     default:
312*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unexpected condition " << condition;
313*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
314*795d594fSAndroid Build Coastguard Worker   }
315*795d594fSAndroid Build Coastguard Worker }
316*795d594fSAndroid Build Coastguard Worker 
HandleGenerateLongTestConstant(HCondition * condition)317*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateLongTestConstant(HCondition* condition) {
318*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64);
319*795d594fSAndroid Build Coastguard Worker 
320*795d594fSAndroid Build Coastguard Worker   IfCondition cond = condition->GetCondition();
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker   HInstruction* right = condition->InputAt(1);
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker   int64_t value = Uint64ConstantFrom(right);
325*795d594fSAndroid Build Coastguard Worker 
326*795d594fSAndroid Build Coastguard Worker   // Comparisons against 0 are common enough, so codegen has special handling for them.
327*795d594fSAndroid Build Coastguard Worker   if (value == 0) {
328*795d594fSAndroid Build Coastguard Worker     switch (cond) {
329*795d594fSAndroid Build Coastguard Worker       case kCondNE:
330*795d594fSAndroid Build Coastguard Worker       case kCondA:
331*795d594fSAndroid Build Coastguard Worker       case kCondEQ:
332*795d594fSAndroid Build Coastguard Worker       case kCondBE:
333*795d594fSAndroid Build Coastguard Worker         // Orrs
334*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
335*795d594fSAndroid Build Coastguard Worker         return;
336*795d594fSAndroid Build Coastguard Worker       case kCondLT:
337*795d594fSAndroid Build Coastguard Worker       case kCondGE:
338*795d594fSAndroid Build Coastguard Worker         // Cmp
339*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
340*795d594fSAndroid Build Coastguard Worker         return;
341*795d594fSAndroid Build Coastguard Worker       case kCondB:
342*795d594fSAndroid Build Coastguard Worker       case kCondAE:
343*795d594fSAndroid Build Coastguard Worker         // Cmp
344*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
345*795d594fSAndroid Build Coastguard Worker         return;
346*795d594fSAndroid Build Coastguard Worker       default:
347*795d594fSAndroid Build Coastguard Worker         break;
348*795d594fSAndroid Build Coastguard Worker     }
349*795d594fSAndroid Build Coastguard Worker   }
350*795d594fSAndroid Build Coastguard Worker 
351*795d594fSAndroid Build Coastguard Worker   switch (cond) {
352*795d594fSAndroid Build Coastguard Worker     case kCondEQ:
353*795d594fSAndroid Build Coastguard Worker     case kCondNE:
354*795d594fSAndroid Build Coastguard Worker     case kCondB:
355*795d594fSAndroid Build Coastguard Worker     case kCondBE:
356*795d594fSAndroid Build Coastguard Worker     case kCondA:
357*795d594fSAndroid Build Coastguard Worker     case kCondAE: {
358*795d594fSAndroid Build Coastguard Worker       // Cmp, IT, Cmp
359*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
360*795d594fSAndroid Build Coastguard Worker       break;
361*795d594fSAndroid Build Coastguard Worker     }
362*795d594fSAndroid Build Coastguard Worker     case kCondLE:
363*795d594fSAndroid Build Coastguard Worker     case kCondGT:
364*795d594fSAndroid Build Coastguard Worker       // Trivially true or false.
365*795d594fSAndroid Build Coastguard Worker       if (value == std::numeric_limits<int64_t>::max()) {
366*795d594fSAndroid Build Coastguard Worker         // Cmp
367*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
368*795d594fSAndroid Build Coastguard Worker         break;
369*795d594fSAndroid Build Coastguard Worker       }
370*795d594fSAndroid Build Coastguard Worker       FALLTHROUGH_INTENDED;
371*795d594fSAndroid Build Coastguard Worker     case kCondGE:
372*795d594fSAndroid Build Coastguard Worker     case kCondLT: {
373*795d594fSAndroid Build Coastguard Worker       // Cmp, Sbcs
374*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
375*795d594fSAndroid Build Coastguard Worker       break;
376*795d594fSAndroid Build Coastguard Worker     }
377*795d594fSAndroid Build Coastguard Worker     default:
378*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unreachable";
379*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
380*795d594fSAndroid Build Coastguard Worker   }
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker 
HandleGenerateLongTest(HCondition * condition)383*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateLongTest(HCondition* condition) {
384*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64);
385*795d594fSAndroid Build Coastguard Worker 
386*795d594fSAndroid Build Coastguard Worker   IfCondition cond = condition->GetCondition();
387*795d594fSAndroid Build Coastguard Worker 
388*795d594fSAndroid Build Coastguard Worker   switch (cond) {
389*795d594fSAndroid Build Coastguard Worker     case kCondEQ:
390*795d594fSAndroid Build Coastguard Worker     case kCondNE:
391*795d594fSAndroid Build Coastguard Worker     case kCondB:
392*795d594fSAndroid Build Coastguard Worker     case kCondBE:
393*795d594fSAndroid Build Coastguard Worker     case kCondA:
394*795d594fSAndroid Build Coastguard Worker     case kCondAE: {
395*795d594fSAndroid Build Coastguard Worker       // Cmp, IT, Cmp
396*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
397*795d594fSAndroid Build Coastguard Worker       break;
398*795d594fSAndroid Build Coastguard Worker     }
399*795d594fSAndroid Build Coastguard Worker     case kCondLE:
400*795d594fSAndroid Build Coastguard Worker     case kCondGT:
401*795d594fSAndroid Build Coastguard Worker     case kCondGE:
402*795d594fSAndroid Build Coastguard Worker     case kCondLT: {
403*795d594fSAndroid Build Coastguard Worker       // Cmp, Sbcs
404*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
405*795d594fSAndroid Build Coastguard Worker       break;
406*795d594fSAndroid Build Coastguard Worker     }
407*795d594fSAndroid Build Coastguard Worker     default:
408*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unreachable";
409*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
410*795d594fSAndroid Build Coastguard Worker   }
411*795d594fSAndroid Build Coastguard Worker }
412*795d594fSAndroid Build Coastguard Worker 
413*795d594fSAndroid Build Coastguard Worker // The GenerateTest series of function all counted as internal latency.
HandleGenerateTest(HCondition * condition)414*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateTest(HCondition* condition) {
415*795d594fSAndroid Build Coastguard Worker   const DataType::Type type = condition->GetLeft()->GetType();
416*795d594fSAndroid Build Coastguard Worker 
417*795d594fSAndroid Build Coastguard Worker   if (type == DataType::Type::kInt64) {
418*795d594fSAndroid Build Coastguard Worker     condition->InputAt(1)->IsConstant()
419*795d594fSAndroid Build Coastguard Worker         ? HandleGenerateLongTestConstant(condition)
420*795d594fSAndroid Build Coastguard Worker         : HandleGenerateLongTest(condition);
421*795d594fSAndroid Build Coastguard Worker   } else if (DataType::IsFloatingPointType(type)) {
422*795d594fSAndroid Build Coastguard Worker     // GenerateVcmp + Vmrs
423*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += 2 * kArmFloatingPointOpLatency;
424*795d594fSAndroid Build Coastguard Worker   } else {
425*795d594fSAndroid Build Coastguard Worker     // Cmp
426*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += kArmIntegerOpLatency;
427*795d594fSAndroid Build Coastguard Worker   }
428*795d594fSAndroid Build Coastguard Worker }
429*795d594fSAndroid Build Coastguard Worker 
CanGenerateTest(HCondition * condition)430*795d594fSAndroid Build Coastguard Worker bool SchedulingLatencyVisitorARM::CanGenerateTest(HCondition* condition) {
431*795d594fSAndroid Build Coastguard Worker   if (condition->GetLeft()->GetType() == DataType::Type::kInt64) {
432*795d594fSAndroid Build Coastguard Worker     HInstruction* right = condition->InputAt(1);
433*795d594fSAndroid Build Coastguard Worker 
434*795d594fSAndroid Build Coastguard Worker     if (right->IsConstant()) {
435*795d594fSAndroid Build Coastguard Worker       IfCondition c = condition->GetCondition();
436*795d594fSAndroid Build Coastguard Worker       const uint64_t value = Uint64ConstantFrom(right);
437*795d594fSAndroid Build Coastguard Worker 
438*795d594fSAndroid Build Coastguard Worker       if (c < kCondLT || c > kCondGE) {
439*795d594fSAndroid Build Coastguard Worker         if (value != 0) {
440*795d594fSAndroid Build Coastguard Worker           return false;
441*795d594fSAndroid Build Coastguard Worker         }
442*795d594fSAndroid Build Coastguard Worker       } else if (c == kCondLE || c == kCondGT) {
443*795d594fSAndroid Build Coastguard Worker         if (value < std::numeric_limits<int64_t>::max() &&
444*795d594fSAndroid Build Coastguard Worker             !codegen_->GetAssembler()->ShifterOperandCanHold(
445*795d594fSAndroid Build Coastguard Worker                 SBC, High32Bits(value + 1), vixl32::FlagsUpdate::SetFlags)) {
446*795d594fSAndroid Build Coastguard Worker           return false;
447*795d594fSAndroid Build Coastguard Worker         }
448*795d594fSAndroid Build Coastguard Worker       } else if (!codegen_->GetAssembler()->ShifterOperandCanHold(
449*795d594fSAndroid Build Coastguard Worker                       SBC, High32Bits(value), vixl32::FlagsUpdate::SetFlags)) {
450*795d594fSAndroid Build Coastguard Worker         return false;
451*795d594fSAndroid Build Coastguard Worker       }
452*795d594fSAndroid Build Coastguard Worker     }
453*795d594fSAndroid Build Coastguard Worker   }
454*795d594fSAndroid Build Coastguard Worker 
455*795d594fSAndroid Build Coastguard Worker   return true;
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker 
HandleGenerateConditionGeneric(HCondition * cond)458*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateConditionGeneric(HCondition* cond) {
459*795d594fSAndroid Build Coastguard Worker   HandleGenerateTest(cond);
460*795d594fSAndroid Build Coastguard Worker 
461*795d594fSAndroid Build Coastguard Worker   // Unlike codegen pass, we cannot check 'out' register IsLow() here,
462*795d594fSAndroid Build Coastguard Worker   // because scheduling is before liveness(location builder) and register allocator,
463*795d594fSAndroid Build Coastguard Worker   // so we can only choose to follow one path of codegen by assuming otu.IsLow() is true.
464*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
465*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmIntegerOpLatency;
466*795d594fSAndroid Build Coastguard Worker }
467*795d594fSAndroid Build Coastguard Worker 
HandleGenerateEqualLong(HCondition * cond)468*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateEqualLong(HCondition* cond) {
469*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64);
470*795d594fSAndroid Build Coastguard Worker 
471*795d594fSAndroid Build Coastguard Worker   IfCondition condition = cond->GetCondition();
472*795d594fSAndroid Build Coastguard Worker 
473*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
474*795d594fSAndroid Build Coastguard Worker 
475*795d594fSAndroid Build Coastguard Worker   if (condition == kCondNE) {
476*795d594fSAndroid Build Coastguard Worker     // Orrs, IT, Mov
477*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
478*795d594fSAndroid Build Coastguard Worker   } else {
479*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += kArmIntegerOpLatency;
480*795d594fSAndroid Build Coastguard Worker     HandleGenerateConditionWithZero(condition);
481*795d594fSAndroid Build Coastguard Worker   }
482*795d594fSAndroid Build Coastguard Worker }
483*795d594fSAndroid Build Coastguard Worker 
HandleGenerateLongComparesAndJumps()484*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateLongComparesAndJumps() {
485*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ += 4 * kArmIntegerOpLatency;
486*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ += kArmBranchLatency;
487*795d594fSAndroid Build Coastguard Worker }
488*795d594fSAndroid Build Coastguard Worker 
HandleGenerateConditionLong(HCondition * cond)489*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateConditionLong(HCondition* cond) {
490*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64);
491*795d594fSAndroid Build Coastguard Worker 
492*795d594fSAndroid Build Coastguard Worker   IfCondition condition = cond->GetCondition();
493*795d594fSAndroid Build Coastguard Worker   HInstruction* right = cond->InputAt(1);
494*795d594fSAndroid Build Coastguard Worker 
495*795d594fSAndroid Build Coastguard Worker   if (right->IsConstant()) {
496*795d594fSAndroid Build Coastguard Worker     // Comparisons against 0 are common enough, so codegen has special handling for them.
497*795d594fSAndroid Build Coastguard Worker     if (Uint64ConstantFrom(right) == 0) {
498*795d594fSAndroid Build Coastguard Worker       switch (condition) {
499*795d594fSAndroid Build Coastguard Worker         case kCondNE:
500*795d594fSAndroid Build Coastguard Worker         case kCondA:
501*795d594fSAndroid Build Coastguard Worker         case kCondEQ:
502*795d594fSAndroid Build Coastguard Worker         case kCondBE:
503*795d594fSAndroid Build Coastguard Worker           // Orr
504*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ += kArmIntegerOpLatency;
505*795d594fSAndroid Build Coastguard Worker           HandleGenerateConditionWithZero(condition);
506*795d594fSAndroid Build Coastguard Worker           return;
507*795d594fSAndroid Build Coastguard Worker         case kCondLT:
508*795d594fSAndroid Build Coastguard Worker         case kCondGE:
509*795d594fSAndroid Build Coastguard Worker           FALLTHROUGH_INTENDED;
510*795d594fSAndroid Build Coastguard Worker         case kCondAE:
511*795d594fSAndroid Build Coastguard Worker         case kCondB:
512*795d594fSAndroid Build Coastguard Worker           HandleGenerateConditionWithZero(condition);
513*795d594fSAndroid Build Coastguard Worker           return;
514*795d594fSAndroid Build Coastguard Worker         case kCondLE:
515*795d594fSAndroid Build Coastguard Worker         case kCondGT:
516*795d594fSAndroid Build Coastguard Worker         default:
517*795d594fSAndroid Build Coastguard Worker           break;
518*795d594fSAndroid Build Coastguard Worker       }
519*795d594fSAndroid Build Coastguard Worker     }
520*795d594fSAndroid Build Coastguard Worker   }
521*795d594fSAndroid Build Coastguard Worker 
522*795d594fSAndroid Build Coastguard Worker   if ((condition == kCondEQ || condition == kCondNE) &&
523*795d594fSAndroid Build Coastguard Worker       !CanGenerateTest(cond)) {
524*795d594fSAndroid Build Coastguard Worker     HandleGenerateEqualLong(cond);
525*795d594fSAndroid Build Coastguard Worker     return;
526*795d594fSAndroid Build Coastguard Worker   }
527*795d594fSAndroid Build Coastguard Worker 
528*795d594fSAndroid Build Coastguard Worker   if (CanGenerateTest(cond)) {
529*795d594fSAndroid Build Coastguard Worker     HandleGenerateConditionGeneric(cond);
530*795d594fSAndroid Build Coastguard Worker     return;
531*795d594fSAndroid Build Coastguard Worker   }
532*795d594fSAndroid Build Coastguard Worker 
533*795d594fSAndroid Build Coastguard Worker   HandleGenerateLongComparesAndJumps();
534*795d594fSAndroid Build Coastguard Worker 
535*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ += kArmIntegerOpLatency;
536*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmBranchLatency;;
537*795d594fSAndroid Build Coastguard Worker }
538*795d594fSAndroid Build Coastguard Worker 
HandleGenerateConditionIntegralOrNonPrimitive(HCondition * cond)539*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateConditionIntegralOrNonPrimitive(HCondition* cond) {
540*795d594fSAndroid Build Coastguard Worker   const DataType::Type type = cond->GetLeft()->GetType();
541*795d594fSAndroid Build Coastguard Worker 
542*795d594fSAndroid Build Coastguard Worker   DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type;
543*795d594fSAndroid Build Coastguard Worker 
544*795d594fSAndroid Build Coastguard Worker   if (type == DataType::Type::kInt64) {
545*795d594fSAndroid Build Coastguard Worker     HandleGenerateConditionLong(cond);
546*795d594fSAndroid Build Coastguard Worker     return;
547*795d594fSAndroid Build Coastguard Worker   }
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker   IfCondition condition = cond->GetCondition();
550*795d594fSAndroid Build Coastguard Worker   HInstruction* right = cond->InputAt(1);
551*795d594fSAndroid Build Coastguard Worker   int64_t value;
552*795d594fSAndroid Build Coastguard Worker 
553*795d594fSAndroid Build Coastguard Worker   if (right->IsConstant()) {
554*795d594fSAndroid Build Coastguard Worker     value = Uint64ConstantFrom(right);
555*795d594fSAndroid Build Coastguard Worker 
556*795d594fSAndroid Build Coastguard Worker     // Comparisons against 0 are common enough, so codegen has special handling for them.
557*795d594fSAndroid Build Coastguard Worker     if (value == 0) {
558*795d594fSAndroid Build Coastguard Worker       switch (condition) {
559*795d594fSAndroid Build Coastguard Worker         case kCondNE:
560*795d594fSAndroid Build Coastguard Worker         case kCondA:
561*795d594fSAndroid Build Coastguard Worker         case kCondEQ:
562*795d594fSAndroid Build Coastguard Worker         case kCondBE:
563*795d594fSAndroid Build Coastguard Worker         case kCondLT:
564*795d594fSAndroid Build Coastguard Worker         case kCondGE:
565*795d594fSAndroid Build Coastguard Worker         case kCondAE:
566*795d594fSAndroid Build Coastguard Worker         case kCondB:
567*795d594fSAndroid Build Coastguard Worker           HandleGenerateConditionWithZero(condition);
568*795d594fSAndroid Build Coastguard Worker           return;
569*795d594fSAndroid Build Coastguard Worker         case kCondLE:
570*795d594fSAndroid Build Coastguard Worker         case kCondGT:
571*795d594fSAndroid Build Coastguard Worker         default:
572*795d594fSAndroid Build Coastguard Worker           break;
573*795d594fSAndroid Build Coastguard Worker       }
574*795d594fSAndroid Build Coastguard Worker     }
575*795d594fSAndroid Build Coastguard Worker   }
576*795d594fSAndroid Build Coastguard Worker 
577*795d594fSAndroid Build Coastguard Worker   if (condition == kCondEQ || condition == kCondNE) {
578*795d594fSAndroid Build Coastguard Worker     if (condition == kCondNE) {
579*795d594fSAndroid Build Coastguard Worker       // CMP, IT, MOV.ne
580*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
581*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;
582*795d594fSAndroid Build Coastguard Worker     } else {
583*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += kArmIntegerOpLatency;
584*795d594fSAndroid Build Coastguard Worker       HandleGenerateConditionWithZero(condition);
585*795d594fSAndroid Build Coastguard Worker     }
586*795d594fSAndroid Build Coastguard Worker     return;
587*795d594fSAndroid Build Coastguard Worker   }
588*795d594fSAndroid Build Coastguard Worker 
589*795d594fSAndroid Build Coastguard Worker   HandleGenerateConditionGeneric(cond);
590*795d594fSAndroid Build Coastguard Worker }
591*795d594fSAndroid Build Coastguard Worker 
HandleCondition(HCondition * cond)592*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleCondition(HCondition* cond) {
593*795d594fSAndroid Build Coastguard Worker   if (cond->IsEmittedAtUseSite()) {
594*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = 0;
595*795d594fSAndroid Build Coastguard Worker     return;
596*795d594fSAndroid Build Coastguard Worker   }
597*795d594fSAndroid Build Coastguard Worker 
598*795d594fSAndroid Build Coastguard Worker   const DataType::Type type = cond->GetLeft()->GetType();
599*795d594fSAndroid Build Coastguard Worker 
600*795d594fSAndroid Build Coastguard Worker   if (DataType::IsFloatingPointType(type)) {
601*795d594fSAndroid Build Coastguard Worker     HandleGenerateConditionGeneric(cond);
602*795d594fSAndroid Build Coastguard Worker     return;
603*795d594fSAndroid Build Coastguard Worker   }
604*795d594fSAndroid Build Coastguard Worker 
605*795d594fSAndroid Build Coastguard Worker   DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type;
606*795d594fSAndroid Build Coastguard Worker 
607*795d594fSAndroid Build Coastguard Worker   const IfCondition condition = cond->GetCondition();
608*795d594fSAndroid Build Coastguard Worker 
609*795d594fSAndroid Build Coastguard Worker   if (type == DataType::Type::kBool &&
610*795d594fSAndroid Build Coastguard Worker       cond->GetRight()->GetType() == DataType::Type::kBool &&
611*795d594fSAndroid Build Coastguard Worker       (condition == kCondEQ || condition == kCondNE)) {
612*795d594fSAndroid Build Coastguard Worker     if (condition == kCondEQ) {
613*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArmIntegerOpLatency;
614*795d594fSAndroid Build Coastguard Worker     }
615*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
616*795d594fSAndroid Build Coastguard Worker     return;
617*795d594fSAndroid Build Coastguard Worker   }
618*795d594fSAndroid Build Coastguard Worker 
619*795d594fSAndroid Build Coastguard Worker   HandleGenerateConditionIntegralOrNonPrimitive(cond);
620*795d594fSAndroid Build Coastguard Worker }
621*795d594fSAndroid Build Coastguard Worker 
VisitCondition(HCondition * instr)622*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitCondition(HCondition* instr) {
623*795d594fSAndroid Build Coastguard Worker   HandleCondition(instr);
624*795d594fSAndroid Build Coastguard Worker }
625*795d594fSAndroid Build Coastguard Worker 
VisitCompare(HCompare * instr)626*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitCompare(HCompare* instr) {
627*795d594fSAndroid Build Coastguard Worker   DataType::Type type = instr->InputAt(0)->GetType();
628*795d594fSAndroid Build Coastguard Worker   switch (type) {
629*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kBool:
630*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint8:
631*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt8:
632*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint16:
633*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt16:
634*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32:
635*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
636*795d594fSAndroid Build Coastguard Worker       break;
637*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
638*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = 2 * kArmIntegerOpLatency + 3 * kArmBranchLatency;
639*795d594fSAndroid Build Coastguard Worker       break;
640*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
641*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
642*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArmIntegerOpLatency + 2 * kArmFloatingPointOpLatency;
643*795d594fSAndroid Build Coastguard Worker       break;
644*795d594fSAndroid Build Coastguard Worker     default:
645*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
646*795d594fSAndroid Build Coastguard Worker       break;
647*795d594fSAndroid Build Coastguard Worker   }
648*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmIntegerOpLatency;
649*795d594fSAndroid Build Coastguard Worker }
650*795d594fSAndroid Build Coastguard Worker 
VisitBitwiseNegatedRight(HBitwiseNegatedRight * instruction)651*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
652*795d594fSAndroid Build Coastguard Worker   if (instruction->GetResultType() == DataType::Type::kInt32) {
653*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
654*795d594fSAndroid Build Coastguard Worker   } else {
655*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArmIntegerOpLatency;
656*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
657*795d594fSAndroid Build Coastguard Worker   }
658*795d594fSAndroid Build Coastguard Worker }
659*795d594fSAndroid Build Coastguard Worker 
HandleGenerateDataProcInstruction(bool internal_latency)660*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateDataProcInstruction(bool internal_latency) {
661*795d594fSAndroid Build Coastguard Worker   if (internal_latency) {
662*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += kArmIntegerOpLatency;
663*795d594fSAndroid Build Coastguard Worker   } else {
664*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmDataProcWithShifterOpLatency;
665*795d594fSAndroid Build Coastguard Worker   }
666*795d594fSAndroid Build Coastguard Worker }
667*795d594fSAndroid Build Coastguard Worker 
HandleGenerateDataProc(HDataProcWithShifterOp * instruction)668*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateDataProc(HDataProcWithShifterOp* instruction) {
669*795d594fSAndroid Build Coastguard Worker   const HInstruction::InstructionKind kind = instruction->GetInstrKind();
670*795d594fSAndroid Build Coastguard Worker   if (kind == HInstruction::kAdd) {
671*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArmIntegerOpLatency;
672*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
673*795d594fSAndroid Build Coastguard Worker   } else if (kind == HInstruction::kSub) {
674*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArmIntegerOpLatency;
675*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
676*795d594fSAndroid Build Coastguard Worker   } else {
677*795d594fSAndroid Build Coastguard Worker     HandleGenerateDataProcInstruction(/* internal_latency= */ true);
678*795d594fSAndroid Build Coastguard Worker     HandleGenerateDataProcInstruction();
679*795d594fSAndroid Build Coastguard Worker   }
680*795d594fSAndroid Build Coastguard Worker }
681*795d594fSAndroid Build Coastguard Worker 
HandleGenerateLongDataProc(HDataProcWithShifterOp * instruction)682*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleGenerateLongDataProc(HDataProcWithShifterOp* instruction) {
683*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
684*795d594fSAndroid Build Coastguard Worker   DCHECK(HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind()));
685*795d594fSAndroid Build Coastguard Worker 
686*795d594fSAndroid Build Coastguard Worker   const uint32_t shift_value = instruction->GetShiftAmount();
687*795d594fSAndroid Build Coastguard Worker   const HInstruction::InstructionKind kind = instruction->GetInstrKind();
688*795d594fSAndroid Build Coastguard Worker 
689*795d594fSAndroid Build Coastguard Worker   if (shift_value >= 32) {
690*795d594fSAndroid Build Coastguard Worker     // Different shift types actually generate similar code here,
691*795d594fSAndroid Build Coastguard Worker     // no need to differentiate shift types like the codegen pass does,
692*795d594fSAndroid Build Coastguard Worker     // which also avoids handling shift types from different ARM backends.
693*795d594fSAndroid Build Coastguard Worker     HandleGenerateDataProc(instruction);
694*795d594fSAndroid Build Coastguard Worker   } else {
695*795d594fSAndroid Build Coastguard Worker     DCHECK_GT(shift_value, 1U);
696*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(shift_value, 32U);
697*795d594fSAndroid Build Coastguard Worker 
698*795d594fSAndroid Build Coastguard Worker     if (kind == HInstruction::kOr || kind == HInstruction::kXor) {
699*795d594fSAndroid Build Coastguard Worker       HandleGenerateDataProcInstruction(/* internal_latency= */ true);
700*795d594fSAndroid Build Coastguard Worker       HandleGenerateDataProcInstruction(/* internal_latency= */ true);
701*795d594fSAndroid Build Coastguard Worker       HandleGenerateDataProcInstruction();
702*795d594fSAndroid Build Coastguard Worker     } else {
703*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
704*795d594fSAndroid Build Coastguard Worker       HandleGenerateDataProc(instruction);
705*795d594fSAndroid Build Coastguard Worker     }
706*795d594fSAndroid Build Coastguard Worker   }
707*795d594fSAndroid Build Coastguard Worker }
708*795d594fSAndroid Build Coastguard Worker 
VisitDataProcWithShifterOp(HDataProcWithShifterOp * instruction)709*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) {
710*795d594fSAndroid Build Coastguard Worker   const HDataProcWithShifterOp::OpKind op_kind = instruction->GetOpKind();
711*795d594fSAndroid Build Coastguard Worker 
712*795d594fSAndroid Build Coastguard Worker   if (instruction->GetType() == DataType::Type::kInt32) {
713*795d594fSAndroid Build Coastguard Worker     HandleGenerateDataProcInstruction();
714*795d594fSAndroid Build Coastguard Worker   } else {
715*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
716*795d594fSAndroid Build Coastguard Worker     if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) {
717*795d594fSAndroid Build Coastguard Worker       HandleGenerateDataProc(instruction);
718*795d594fSAndroid Build Coastguard Worker     } else {
719*795d594fSAndroid Build Coastguard Worker       HandleGenerateLongDataProc(instruction);
720*795d594fSAndroid Build Coastguard Worker     }
721*795d594fSAndroid Build Coastguard Worker   }
722*795d594fSAndroid Build Coastguard Worker }
723*795d594fSAndroid Build Coastguard Worker 
VisitIntermediateAddress(HIntermediateAddress *)724*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitIntermediateAddress([[maybe_unused]] HIntermediateAddress*) {
725*795d594fSAndroid Build Coastguard Worker   // Although the code generated is a simple `add` instruction, we found through empirical results
726*795d594fSAndroid Build Coastguard Worker   // that spacing it from its use in memory accesses was beneficial.
727*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArmNopLatency;
728*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmIntegerOpLatency;
729*795d594fSAndroid Build Coastguard Worker }
730*795d594fSAndroid Build Coastguard Worker 
VisitIntermediateAddressIndex(HIntermediateAddressIndex *)731*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitIntermediateAddressIndex(
732*795d594fSAndroid Build Coastguard Worker     [[maybe_unused]] HIntermediateAddressIndex*) {
733*795d594fSAndroid Build Coastguard Worker   UNIMPLEMENTED(FATAL) << "IntermediateAddressIndex is not implemented for ARM";
734*795d594fSAndroid Build Coastguard Worker }
735*795d594fSAndroid Build Coastguard Worker 
VisitMultiplyAccumulate(HMultiplyAccumulate *)736*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitMultiplyAccumulate([[maybe_unused]] HMultiplyAccumulate*) {
737*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmMulIntegerLatency;
738*795d594fSAndroid Build Coastguard Worker }
739*795d594fSAndroid Build Coastguard Worker 
VisitArrayGet(HArrayGet * instruction)740*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) {
741*795d594fSAndroid Build Coastguard Worker   DataType::Type type = instruction->GetType();
742*795d594fSAndroid Build Coastguard Worker   const bool maybe_compressed_char_at =
743*795d594fSAndroid Build Coastguard Worker       mirror::kUseStringCompression && instruction->IsStringCharAt();
744*795d594fSAndroid Build Coastguard Worker   HInstruction* array_instr = instruction->GetArray();
745*795d594fSAndroid Build Coastguard Worker   bool has_intermediate_address = array_instr->IsIntermediateAddress();
746*795d594fSAndroid Build Coastguard Worker   HInstruction* index = instruction->InputAt(1);
747*795d594fSAndroid Build Coastguard Worker 
748*795d594fSAndroid Build Coastguard Worker   switch (type) {
749*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kBool:
750*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint8:
751*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt8:
752*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint16:
753*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt16:
754*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32: {
755*795d594fSAndroid Build Coastguard Worker       if (maybe_compressed_char_at) {
756*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmMemoryLoadLatency;
757*795d594fSAndroid Build Coastguard Worker       }
758*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
759*795d594fSAndroid Build Coastguard Worker         if (maybe_compressed_char_at) {
760*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ +=
761*795d594fSAndroid Build Coastguard Worker               kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
762*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmBranchLatency;
763*795d594fSAndroid Build Coastguard Worker         } else {
764*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ += kArmMemoryLoadLatency;
765*795d594fSAndroid Build Coastguard Worker         }
766*795d594fSAndroid Build Coastguard Worker       } else {
767*795d594fSAndroid Build Coastguard Worker         if (has_intermediate_address) {
768*795d594fSAndroid Build Coastguard Worker         } else {
769*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ += kArmIntegerOpLatency;
770*795d594fSAndroid Build Coastguard Worker         }
771*795d594fSAndroid Build Coastguard Worker         if (maybe_compressed_char_at) {
772*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ +=
773*795d594fSAndroid Build Coastguard Worker               kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
774*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmBranchLatency;
775*795d594fSAndroid Build Coastguard Worker         } else {
776*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ += kArmMemoryLoadLatency;
777*795d594fSAndroid Build Coastguard Worker         }
778*795d594fSAndroid Build Coastguard Worker       }
779*795d594fSAndroid Build Coastguard Worker       break;
780*795d594fSAndroid Build Coastguard Worker     }
781*795d594fSAndroid Build Coastguard Worker 
782*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kReference: {
783*795d594fSAndroid Build Coastguard Worker       if (codegen_->EmitBakerReadBarrier()) {
784*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmLoadWithBakerReadBarrierLatency;
785*795d594fSAndroid Build Coastguard Worker       } else {
786*795d594fSAndroid Build Coastguard Worker         if (index->IsConstant()) {
787*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmMemoryLoadLatency;
788*795d594fSAndroid Build Coastguard Worker         } else {
789*795d594fSAndroid Build Coastguard Worker           if (has_intermediate_address) {
790*795d594fSAndroid Build Coastguard Worker           } else {
791*795d594fSAndroid Build Coastguard Worker             last_visited_internal_latency_ += kArmIntegerOpLatency;
792*795d594fSAndroid Build Coastguard Worker           }
793*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmMemoryLoadLatency;
794*795d594fSAndroid Build Coastguard Worker         }
795*795d594fSAndroid Build Coastguard Worker       }
796*795d594fSAndroid Build Coastguard Worker       break;
797*795d594fSAndroid Build Coastguard Worker     }
798*795d594fSAndroid Build Coastguard Worker 
799*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64: {
800*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
801*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
802*795d594fSAndroid Build Coastguard Worker       } else {
803*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
804*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
805*795d594fSAndroid Build Coastguard Worker       }
806*795d594fSAndroid Build Coastguard Worker       break;
807*795d594fSAndroid Build Coastguard Worker     }
808*795d594fSAndroid Build Coastguard Worker 
809*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32: {
810*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
811*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
812*795d594fSAndroid Build Coastguard Worker       } else {
813*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
814*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
815*795d594fSAndroid Build Coastguard Worker       }
816*795d594fSAndroid Build Coastguard Worker       break;
817*795d594fSAndroid Build Coastguard Worker     }
818*795d594fSAndroid Build Coastguard Worker 
819*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64: {
820*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
821*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
822*795d594fSAndroid Build Coastguard Worker       } else {
823*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency;
824*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
825*795d594fSAndroid Build Coastguard Worker       }
826*795d594fSAndroid Build Coastguard Worker       break;
827*795d594fSAndroid Build Coastguard Worker     }
828*795d594fSAndroid Build Coastguard Worker 
829*795d594fSAndroid Build Coastguard Worker     default:
830*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unreachable type " << type;
831*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
832*795d594fSAndroid Build Coastguard Worker   }
833*795d594fSAndroid Build Coastguard Worker }
834*795d594fSAndroid Build Coastguard Worker 
VisitArrayLength(HArrayLength * instruction)835*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitArrayLength(HArrayLength* instruction) {
836*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmMemoryLoadLatency;
837*795d594fSAndroid Build Coastguard Worker   if (mirror::kUseStringCompression && instruction->IsStringLength()) {
838*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArmMemoryLoadLatency;
839*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
840*795d594fSAndroid Build Coastguard Worker   }
841*795d594fSAndroid Build Coastguard Worker }
842*795d594fSAndroid Build Coastguard Worker 
VisitArraySet(HArraySet * instruction)843*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) {
844*795d594fSAndroid Build Coastguard Worker   HInstruction* index = instruction->InputAt(1);
845*795d594fSAndroid Build Coastguard Worker   DataType::Type value_type = instruction->GetComponentType();
846*795d594fSAndroid Build Coastguard Worker   HInstruction* array_instr = instruction->GetArray();
847*795d594fSAndroid Build Coastguard Worker   bool has_intermediate_address = array_instr->IsIntermediateAddress();
848*795d594fSAndroid Build Coastguard Worker 
849*795d594fSAndroid Build Coastguard Worker   switch (value_type) {
850*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kBool:
851*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint8:
852*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt8:
853*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint16:
854*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt16:
855*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32: {
856*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
857*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryStoreLatency;
858*795d594fSAndroid Build Coastguard Worker       } else {
859*795d594fSAndroid Build Coastguard Worker         if (has_intermediate_address) {
860*795d594fSAndroid Build Coastguard Worker         } else {
861*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmIntegerOpLatency;
862*795d594fSAndroid Build Coastguard Worker         }
863*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryStoreLatency;
864*795d594fSAndroid Build Coastguard Worker       }
865*795d594fSAndroid Build Coastguard Worker       break;
866*795d594fSAndroid Build Coastguard Worker     }
867*795d594fSAndroid Build Coastguard Worker 
868*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kReference: {
869*795d594fSAndroid Build Coastguard Worker       if (instruction->InputAt(2)->IsNullConstant()) {
870*795d594fSAndroid Build Coastguard Worker         if (index->IsConstant()) {
871*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmMemoryStoreLatency;
872*795d594fSAndroid Build Coastguard Worker         } else {
873*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmIntegerOpLatency;
874*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmMemoryStoreLatency;
875*795d594fSAndroid Build Coastguard Worker         }
876*795d594fSAndroid Build Coastguard Worker       } else {
877*795d594fSAndroid Build Coastguard Worker         // Following the exact instructions of runtime type checks is too complicated,
878*795d594fSAndroid Build Coastguard Worker         // just giving it a simple slow latency.
879*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmRuntimeTypeCheckLatency;
880*795d594fSAndroid Build Coastguard Worker       }
881*795d594fSAndroid Build Coastguard Worker       break;
882*795d594fSAndroid Build Coastguard Worker     }
883*795d594fSAndroid Build Coastguard Worker 
884*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64: {
885*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
886*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
887*795d594fSAndroid Build Coastguard Worker       } else {
888*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmIntegerOpLatency;
889*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
890*795d594fSAndroid Build Coastguard Worker       }
891*795d594fSAndroid Build Coastguard Worker       break;
892*795d594fSAndroid Build Coastguard Worker     }
893*795d594fSAndroid Build Coastguard Worker 
894*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32: {
895*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
896*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
897*795d594fSAndroid Build Coastguard Worker       } else {
898*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmIntegerOpLatency;
899*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
900*795d594fSAndroid Build Coastguard Worker       }
901*795d594fSAndroid Build Coastguard Worker       break;
902*795d594fSAndroid Build Coastguard Worker     }
903*795d594fSAndroid Build Coastguard Worker 
904*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64: {
905*795d594fSAndroid Build Coastguard Worker       if (index->IsConstant()) {
906*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
907*795d594fSAndroid Build Coastguard Worker       } else {
908*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmIntegerOpLatency;
909*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
910*795d594fSAndroid Build Coastguard Worker       }
911*795d594fSAndroid Build Coastguard Worker       break;
912*795d594fSAndroid Build Coastguard Worker     }
913*795d594fSAndroid Build Coastguard Worker 
914*795d594fSAndroid Build Coastguard Worker     default:
915*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unreachable type " << value_type;
916*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
917*795d594fSAndroid Build Coastguard Worker   }
918*795d594fSAndroid Build Coastguard Worker }
919*795d594fSAndroid Build Coastguard Worker 
VisitBoundsCheck(HBoundsCheck *)920*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitBoundsCheck([[maybe_unused]] HBoundsCheck*) {
921*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArmIntegerOpLatency;
922*795d594fSAndroid Build Coastguard Worker   // Users do not use any data results.
923*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = 0;
924*795d594fSAndroid Build Coastguard Worker }
925*795d594fSAndroid Build Coastguard Worker 
HandleDivRemConstantIntegralLatencies(int32_t imm)926*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleDivRemConstantIntegralLatencies(int32_t imm) {
927*795d594fSAndroid Build Coastguard Worker   if (imm == 0) {
928*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = 0;
929*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = 0;
930*795d594fSAndroid Build Coastguard Worker   } else if (imm == 1 || imm == -1) {
931*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
932*795d594fSAndroid Build Coastguard Worker   } else if (IsPowerOfTwo(AbsOrMin(imm))) {
933*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = 3 * kArmIntegerOpLatency;
934*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
935*795d594fSAndroid Build Coastguard Worker   } else {
936*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArmMulIntegerLatency + 2 * kArmIntegerOpLatency;
937*795d594fSAndroid Build Coastguard Worker     last_visited_latency_ = kArmIntegerOpLatency;
938*795d594fSAndroid Build Coastguard Worker   }
939*795d594fSAndroid Build Coastguard Worker }
940*795d594fSAndroid Build Coastguard Worker 
VisitDiv(HDiv * instruction)941*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitDiv(HDiv* instruction) {
942*795d594fSAndroid Build Coastguard Worker   DataType::Type type = instruction->GetResultType();
943*795d594fSAndroid Build Coastguard Worker   switch (type) {
944*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32: {
945*795d594fSAndroid Build Coastguard Worker       HInstruction* rhs = instruction->GetRight();
946*795d594fSAndroid Build Coastguard Worker       if (rhs->IsConstant()) {
947*795d594fSAndroid Build Coastguard Worker         int32_t imm = Int32ConstantFrom(rhs->AsConstant());
948*795d594fSAndroid Build Coastguard Worker         HandleDivRemConstantIntegralLatencies(imm);
949*795d594fSAndroid Build Coastguard Worker       } else {
950*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmDivIntegerLatency;
951*795d594fSAndroid Build Coastguard Worker       }
952*795d594fSAndroid Build Coastguard Worker       break;
953*795d594fSAndroid Build Coastguard Worker     }
954*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
955*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmDivFloatLatency;
956*795d594fSAndroid Build Coastguard Worker       break;
957*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
958*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmDivDoubleLatency;
959*795d594fSAndroid Build Coastguard Worker       break;
960*795d594fSAndroid Build Coastguard Worker     default:
961*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArmCallInternalLatency;
962*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmCallLatency;
963*795d594fSAndroid Build Coastguard Worker       break;
964*795d594fSAndroid Build Coastguard Worker   }
965*795d594fSAndroid Build Coastguard Worker }
966*795d594fSAndroid Build Coastguard Worker 
VisitInstanceFieldGet(HInstanceFieldGet * instruction)967*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
968*795d594fSAndroid Build Coastguard Worker   HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
969*795d594fSAndroid Build Coastguard Worker }
970*795d594fSAndroid Build Coastguard Worker 
VisitInstanceFieldSet(HInstanceFieldSet * instruction)971*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
972*795d594fSAndroid Build Coastguard Worker   HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
973*795d594fSAndroid Build Coastguard Worker }
974*795d594fSAndroid Build Coastguard Worker 
VisitInstanceOf(HInstanceOf *)975*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitInstanceOf([[maybe_unused]] HInstanceOf*) {
976*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArmCallInternalLatency;
977*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmIntegerOpLatency;
978*795d594fSAndroid Build Coastguard Worker }
979*795d594fSAndroid Build Coastguard Worker 
VisitInvoke(HInvoke *)980*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitInvoke([[maybe_unused]] HInvoke*) {
981*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArmCallInternalLatency;
982*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmCallLatency;
983*795d594fSAndroid Build Coastguard Worker }
984*795d594fSAndroid Build Coastguard Worker 
VisitLoadString(HLoadString *)985*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitLoadString([[maybe_unused]] HLoadString*) {
986*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArmLoadStringInternalLatency;
987*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmMemoryLoadLatency;
988*795d594fSAndroid Build Coastguard Worker }
989*795d594fSAndroid Build Coastguard Worker 
VisitNewArray(HNewArray *)990*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitNewArray([[maybe_unused]] HNewArray*) {
991*795d594fSAndroid Build Coastguard Worker   last_visited_internal_latency_ = kArmIntegerOpLatency + kArmCallInternalLatency;
992*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmCallLatency;
993*795d594fSAndroid Build Coastguard Worker }
994*795d594fSAndroid Build Coastguard Worker 
VisitNewInstance(HNewInstance * instruction)995*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitNewInstance(HNewInstance* instruction) {
996*795d594fSAndroid Build Coastguard Worker   if (instruction->IsStringAlloc()) {
997*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = 2 * kArmMemoryLoadLatency + kArmCallInternalLatency;
998*795d594fSAndroid Build Coastguard Worker   } else {
999*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ = kArmCallInternalLatency;
1000*795d594fSAndroid Build Coastguard Worker   }
1001*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = kArmCallLatency;
1002*795d594fSAndroid Build Coastguard Worker }
1003*795d594fSAndroid Build Coastguard Worker 
VisitRem(HRem * instruction)1004*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitRem(HRem* instruction) {
1005*795d594fSAndroid Build Coastguard Worker   DataType::Type type = instruction->GetResultType();
1006*795d594fSAndroid Build Coastguard Worker   switch (type) {
1007*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32: {
1008*795d594fSAndroid Build Coastguard Worker       HInstruction* rhs = instruction->GetRight();
1009*795d594fSAndroid Build Coastguard Worker       if (rhs->IsConstant()) {
1010*795d594fSAndroid Build Coastguard Worker         int32_t imm = Int32ConstantFrom(rhs->AsConstant());
1011*795d594fSAndroid Build Coastguard Worker         HandleDivRemConstantIntegralLatencies(imm);
1012*795d594fSAndroid Build Coastguard Worker       } else {
1013*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmDivIntegerLatency;
1014*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMulIntegerLatency;
1015*795d594fSAndroid Build Coastguard Worker       }
1016*795d594fSAndroid Build Coastguard Worker       break;
1017*795d594fSAndroid Build Coastguard Worker     }
1018*795d594fSAndroid Build Coastguard Worker     default:
1019*795d594fSAndroid Build Coastguard Worker       last_visited_internal_latency_ = kArmCallInternalLatency;
1020*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmCallLatency;
1021*795d594fSAndroid Build Coastguard Worker       break;
1022*795d594fSAndroid Build Coastguard Worker   }
1023*795d594fSAndroid Build Coastguard Worker }
1024*795d594fSAndroid Build Coastguard Worker 
HandleFieldGetLatencies(HInstruction * instruction,const FieldInfo & field_info)1025*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruction,
1026*795d594fSAndroid Build Coastguard Worker                                                           const FieldInfo& field_info) {
1027*795d594fSAndroid Build Coastguard Worker   DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
1028*795d594fSAndroid Build Coastguard Worker   DCHECK(codegen_ != nullptr);
1029*795d594fSAndroid Build Coastguard Worker   bool is_volatile = field_info.IsVolatile();
1030*795d594fSAndroid Build Coastguard Worker   DataType::Type field_type = field_info.GetFieldType();
1031*795d594fSAndroid Build Coastguard Worker   bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
1032*795d594fSAndroid Build Coastguard Worker 
1033*795d594fSAndroid Build Coastguard Worker   switch (field_type) {
1034*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kBool:
1035*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint8:
1036*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt8:
1037*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint16:
1038*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt16:
1039*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32:
1040*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMemoryLoadLatency;
1041*795d594fSAndroid Build Coastguard Worker       break;
1042*795d594fSAndroid Build Coastguard Worker 
1043*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kReference:
1044*795d594fSAndroid Build Coastguard Worker       if (codegen_->EmitBakerReadBarrier()) {
1045*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
1046*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
1047*795d594fSAndroid Build Coastguard Worker       } else {
1048*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
1049*795d594fSAndroid Build Coastguard Worker       }
1050*795d594fSAndroid Build Coastguard Worker       break;
1051*795d594fSAndroid Build Coastguard Worker 
1052*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
1053*795d594fSAndroid Build Coastguard Worker       if (is_volatile && !atomic_ldrd_strd) {
1054*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
1055*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
1056*795d594fSAndroid Build Coastguard Worker       } else {
1057*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
1058*795d594fSAndroid Build Coastguard Worker       }
1059*795d594fSAndroid Build Coastguard Worker       break;
1060*795d594fSAndroid Build Coastguard Worker 
1061*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
1062*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMemoryLoadLatency;
1063*795d594fSAndroid Build Coastguard Worker       break;
1064*795d594fSAndroid Build Coastguard Worker 
1065*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
1066*795d594fSAndroid Build Coastguard Worker       if (is_volatile && !atomic_ldrd_strd) {
1067*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ =
1068*795d594fSAndroid Build Coastguard Worker             kArmMemoryLoadLatency + kArmIntegerOpLatency + kArmMemoryLoadLatency;
1069*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmIntegerOpLatency;
1070*795d594fSAndroid Build Coastguard Worker       } else {
1071*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryLoadLatency;
1072*795d594fSAndroid Build Coastguard Worker       }
1073*795d594fSAndroid Build Coastguard Worker       break;
1074*795d594fSAndroid Build Coastguard Worker 
1075*795d594fSAndroid Build Coastguard Worker     default:
1076*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMemoryLoadLatency;
1077*795d594fSAndroid Build Coastguard Worker       break;
1078*795d594fSAndroid Build Coastguard Worker   }
1079*795d594fSAndroid Build Coastguard Worker 
1080*795d594fSAndroid Build Coastguard Worker   if (is_volatile) {
1081*795d594fSAndroid Build Coastguard Worker     last_visited_internal_latency_ += kArmMemoryBarrierLatency;
1082*795d594fSAndroid Build Coastguard Worker   }
1083*795d594fSAndroid Build Coastguard Worker }
1084*795d594fSAndroid Build Coastguard Worker 
HandleFieldSetLatencies(HInstruction * instruction,const FieldInfo & field_info)1085*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruction,
1086*795d594fSAndroid Build Coastguard Worker                                                           const FieldInfo& field_info) {
1087*795d594fSAndroid Build Coastguard Worker   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
1088*795d594fSAndroid Build Coastguard Worker   DCHECK(codegen_ != nullptr);
1089*795d594fSAndroid Build Coastguard Worker   bool is_volatile = field_info.IsVolatile();
1090*795d594fSAndroid Build Coastguard Worker   DataType::Type field_type = field_info.GetFieldType();
1091*795d594fSAndroid Build Coastguard Worker   bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
1092*795d594fSAndroid Build Coastguard Worker 
1093*795d594fSAndroid Build Coastguard Worker   switch (field_type) {
1094*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kBool:
1095*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint8:
1096*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt8:
1097*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint16:
1098*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt16:
1099*795d594fSAndroid Build Coastguard Worker       if (is_volatile) {
1100*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmMemoryBarrierLatency + kArmMemoryStoreLatency;
1101*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryBarrierLatency;
1102*795d594fSAndroid Build Coastguard Worker       } else {
1103*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryStoreLatency;
1104*795d594fSAndroid Build Coastguard Worker       }
1105*795d594fSAndroid Build Coastguard Worker       break;
1106*795d594fSAndroid Build Coastguard Worker 
1107*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32:
1108*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kReference:
1109*795d594fSAndroid Build Coastguard Worker       if (kPoisonHeapReferences && field_type == DataType::Type::kReference) {
1110*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ += kArmIntegerOpLatency * 2;
1111*795d594fSAndroid Build Coastguard Worker       }
1112*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMemoryStoreLatency;
1113*795d594fSAndroid Build Coastguard Worker       break;
1114*795d594fSAndroid Build Coastguard Worker 
1115*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
1116*795d594fSAndroid Build Coastguard Worker       if (is_volatile && !atomic_ldrd_strd) {
1117*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ =
1118*795d594fSAndroid Build Coastguard Worker             kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1119*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmIntegerOpLatency;
1120*795d594fSAndroid Build Coastguard Worker       } else {
1121*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryStoreLatency;
1122*795d594fSAndroid Build Coastguard Worker       }
1123*795d594fSAndroid Build Coastguard Worker       break;
1124*795d594fSAndroid Build Coastguard Worker 
1125*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
1126*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMemoryStoreLatency;
1127*795d594fSAndroid Build Coastguard Worker       break;
1128*795d594fSAndroid Build Coastguard Worker 
1129*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
1130*795d594fSAndroid Build Coastguard Worker       if (is_volatile && !atomic_ldrd_strd) {
1131*795d594fSAndroid Build Coastguard Worker         last_visited_internal_latency_ = kArmIntegerOpLatency +
1132*795d594fSAndroid Build Coastguard Worker             kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1133*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmIntegerOpLatency;
1134*795d594fSAndroid Build Coastguard Worker       } else {
1135*795d594fSAndroid Build Coastguard Worker         last_visited_latency_ = kArmMemoryStoreLatency;
1136*795d594fSAndroid Build Coastguard Worker       }
1137*795d594fSAndroid Build Coastguard Worker       break;
1138*795d594fSAndroid Build Coastguard Worker 
1139*795d594fSAndroid Build Coastguard Worker     default:
1140*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmMemoryStoreLatency;
1141*795d594fSAndroid Build Coastguard Worker       break;
1142*795d594fSAndroid Build Coastguard Worker   }
1143*795d594fSAndroid Build Coastguard Worker }
1144*795d594fSAndroid Build Coastguard Worker 
VisitStaticFieldGet(HStaticFieldGet * instruction)1145*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitStaticFieldGet(HStaticFieldGet* instruction) {
1146*795d594fSAndroid Build Coastguard Worker   HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
1147*795d594fSAndroid Build Coastguard Worker }
1148*795d594fSAndroid Build Coastguard Worker 
VisitStaticFieldSet(HStaticFieldSet * instruction)1149*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
1150*795d594fSAndroid Build Coastguard Worker   HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
1151*795d594fSAndroid Build Coastguard Worker }
1152*795d594fSAndroid Build Coastguard Worker 
VisitSuspendCheck(HSuspendCheck * instruction)1153*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitSuspendCheck(HSuspendCheck* instruction) {
1154*795d594fSAndroid Build Coastguard Worker   HBasicBlock* block = instruction->GetBlock();
1155*795d594fSAndroid Build Coastguard Worker   DCHECK_IMPLIES(block->GetLoopInformation() == nullptr,
1156*795d594fSAndroid Build Coastguard Worker                  block->IsEntryBlock() && instruction->GetNext()->IsGoto());
1157*795d594fSAndroid Build Coastguard Worker   // Users do not use any data results.
1158*795d594fSAndroid Build Coastguard Worker   last_visited_latency_ = 0;
1159*795d594fSAndroid Build Coastguard Worker }
1160*795d594fSAndroid Build Coastguard Worker 
VisitTypeConversion(HTypeConversion * instr)1161*795d594fSAndroid Build Coastguard Worker void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) {
1162*795d594fSAndroid Build Coastguard Worker   DataType::Type result_type = instr->GetResultType();
1163*795d594fSAndroid Build Coastguard Worker   DataType::Type input_type = instr->GetInputType();
1164*795d594fSAndroid Build Coastguard Worker 
1165*795d594fSAndroid Build Coastguard Worker   switch (result_type) {
1166*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint8:
1167*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt8:
1168*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kUint16:
1169*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt16:
1170*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmIntegerOpLatency;  // SBFX or UBFX
1171*795d594fSAndroid Build Coastguard Worker       break;
1172*795d594fSAndroid Build Coastguard Worker 
1173*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt32:
1174*795d594fSAndroid Build Coastguard Worker       switch (input_type) {
1175*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt64:
1176*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmIntegerOpLatency;  // MOV
1177*795d594fSAndroid Build Coastguard Worker           break;
1178*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kFloat32:
1179*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kFloat64:
1180*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1181*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1182*795d594fSAndroid Build Coastguard Worker           break;
1183*795d594fSAndroid Build Coastguard Worker         default:
1184*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmIntegerOpLatency;
1185*795d594fSAndroid Build Coastguard Worker           break;
1186*795d594fSAndroid Build Coastguard Worker       }
1187*795d594fSAndroid Build Coastguard Worker       break;
1188*795d594fSAndroid Build Coastguard Worker 
1189*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kInt64:
1190*795d594fSAndroid Build Coastguard Worker       switch (input_type) {
1191*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kBool:
1192*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kUint8:
1193*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt8:
1194*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kUint16:
1195*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt16:
1196*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt32:
1197*795d594fSAndroid Build Coastguard Worker           // MOV and extension
1198*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmIntegerOpLatency;
1199*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmIntegerOpLatency;
1200*795d594fSAndroid Build Coastguard Worker           break;
1201*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kFloat32:
1202*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kFloat64:
1203*795d594fSAndroid Build Coastguard Worker           // invokes runtime
1204*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmCallInternalLatency;
1205*795d594fSAndroid Build Coastguard Worker           break;
1206*795d594fSAndroid Build Coastguard Worker         default:
1207*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmIntegerOpLatency;
1208*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmIntegerOpLatency;
1209*795d594fSAndroid Build Coastguard Worker           break;
1210*795d594fSAndroid Build Coastguard Worker       }
1211*795d594fSAndroid Build Coastguard Worker       break;
1212*795d594fSAndroid Build Coastguard Worker 
1213*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat32:
1214*795d594fSAndroid Build Coastguard Worker       switch (input_type) {
1215*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kBool:
1216*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kUint8:
1217*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt8:
1218*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kUint16:
1219*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt16:
1220*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt32:
1221*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1222*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1223*795d594fSAndroid Build Coastguard Worker           break;
1224*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt64:
1225*795d594fSAndroid Build Coastguard Worker           // invokes runtime
1226*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmCallInternalLatency;
1227*795d594fSAndroid Build Coastguard Worker           break;
1228*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kFloat64:
1229*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1230*795d594fSAndroid Build Coastguard Worker           break;
1231*795d594fSAndroid Build Coastguard Worker         default:
1232*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1233*795d594fSAndroid Build Coastguard Worker           break;
1234*795d594fSAndroid Build Coastguard Worker       }
1235*795d594fSAndroid Build Coastguard Worker       break;
1236*795d594fSAndroid Build Coastguard Worker 
1237*795d594fSAndroid Build Coastguard Worker     case DataType::Type::kFloat64:
1238*795d594fSAndroid Build Coastguard Worker       switch (input_type) {
1239*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kBool:
1240*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kUint8:
1241*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt8:
1242*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kUint16:
1243*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt16:
1244*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt32:
1245*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1246*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1247*795d594fSAndroid Build Coastguard Worker           break;
1248*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kInt64:
1249*795d594fSAndroid Build Coastguard Worker           last_visited_internal_latency_ = 5 * kArmFloatingPointOpLatency;
1250*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1251*795d594fSAndroid Build Coastguard Worker           break;
1252*795d594fSAndroid Build Coastguard Worker         case DataType::Type::kFloat32:
1253*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1254*795d594fSAndroid Build Coastguard Worker           break;
1255*795d594fSAndroid Build Coastguard Worker         default:
1256*795d594fSAndroid Build Coastguard Worker           last_visited_latency_ = kArmFloatingPointOpLatency;
1257*795d594fSAndroid Build Coastguard Worker           break;
1258*795d594fSAndroid Build Coastguard Worker       }
1259*795d594fSAndroid Build Coastguard Worker       break;
1260*795d594fSAndroid Build Coastguard Worker 
1261*795d594fSAndroid Build Coastguard Worker     default:
1262*795d594fSAndroid Build Coastguard Worker       last_visited_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1263*795d594fSAndroid Build Coastguard Worker       break;
1264*795d594fSAndroid Build Coastguard Worker   }
1265*795d594fSAndroid Build Coastguard Worker }
1266*795d594fSAndroid Build Coastguard Worker 
IsSchedulable(const HInstruction * instruction) const1267*795d594fSAndroid Build Coastguard Worker bool HSchedulerARM::IsSchedulable(const HInstruction* instruction) const {
1268*795d594fSAndroid Build Coastguard Worker   switch (instruction->GetKind()) {
1269*795d594fSAndroid Build Coastguard Worker #define SCHEDULABLE_CASE(type, unused)            \
1270*795d594fSAndroid Build Coastguard Worker     case HInstruction::InstructionKind::k##type:  \
1271*795d594fSAndroid Build Coastguard Worker       return true;
1272*795d594fSAndroid Build Coastguard Worker     FOR_EACH_SCHEDULED_SHARED_INSTRUCTION(SCHEDULABLE_CASE)
1273*795d594fSAndroid Build Coastguard Worker     FOR_EACH_CONCRETE_INSTRUCTION_ARM(SCHEDULABLE_CASE)
1274*795d594fSAndroid Build Coastguard Worker #undef SCHEDULABLE_CASE
1275*795d594fSAndroid Build Coastguard Worker 
1276*795d594fSAndroid Build Coastguard Worker     default:
1277*795d594fSAndroid Build Coastguard Worker       return HScheduler::IsSchedulable(instruction);
1278*795d594fSAndroid Build Coastguard Worker   }
1279*795d594fSAndroid Build Coastguard Worker }
1280*795d594fSAndroid Build Coastguard Worker 
BuildSchedulingGraph(HBasicBlock * block,ScopedArenaAllocator * allocator,const HeapLocationCollector * heap_location_collector)1281*795d594fSAndroid Build Coastguard Worker std::pair<SchedulingGraph, ScopedArenaVector<SchedulingNode*>> HSchedulerARM::BuildSchedulingGraph(
1282*795d594fSAndroid Build Coastguard Worker     HBasicBlock* block,
1283*795d594fSAndroid Build Coastguard Worker     ScopedArenaAllocator* allocator,
1284*795d594fSAndroid Build Coastguard Worker     const HeapLocationCollector* heap_location_collector) {
1285*795d594fSAndroid Build Coastguard Worker   SchedulingLatencyVisitorARM latency_visitor(codegen_);
1286*795d594fSAndroid Build Coastguard Worker   return HScheduler::BuildSchedulingGraph(
1287*795d594fSAndroid Build Coastguard Worker       block, allocator, heap_location_collector, &latency_visitor);
1288*795d594fSAndroid Build Coastguard Worker }
1289*795d594fSAndroid Build Coastguard Worker 
1290*795d594fSAndroid Build Coastguard Worker }  // namespace arm
1291*795d594fSAndroid Build Coastguard Worker }  // namespace art
1292