blob: 110db47eb516c73e62d3fc54bc2956985cafb8fb [file] [log] [blame]
xueliang.zhongf7caf682017-03-01 16:07:02 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070017#include "scheduler_arm.h"
18
xueliang.zhongf7caf682017-03-01 16:07:02 +000019#include "arch/arm/instruction_set_features_arm.h"
20#include "code_generator_utils.h"
21#include "common_arm.h"
Andreas Gampe09659c22017-09-18 18:23:32 -070022#include "heap_poisoning.h"
xueliang.zhongf7caf682017-03-01 16:07:02 +000023#include "mirror/array-inl.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070024#include "mirror/string.h"
xueliang.zhongf7caf682017-03-01 16:07:02 +000025
26namespace art {
27namespace arm {
28
29using helpers::Int32ConstantFrom;
30using helpers::Uint64ConstantFrom;
31
32void SchedulingLatencyVisitorARM::HandleBinaryOperationLantencies(HBinaryOperation* instr) {
33 switch (instr->GetResultType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010034 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +000035 // HAdd and HSub long operations translate to ADDS+ADC or SUBS+SBC pairs,
36 // so a bubble (kArmNopLatency) is added to represent the internal carry flag
37 // dependency inside these pairs.
38 last_visited_internal_latency_ = kArmIntegerOpLatency + kArmNopLatency;
39 last_visited_latency_ = kArmIntegerOpLatency;
40 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010041 case DataType::Type::kFloat32:
42 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +000043 last_visited_latency_ = kArmFloatingPointOpLatency;
44 break;
45 default:
46 last_visited_latency_ = kArmIntegerOpLatency;
47 break;
48 }
49}
50
51void SchedulingLatencyVisitorARM::VisitAdd(HAdd* instr) {
52 HandleBinaryOperationLantencies(instr);
53}
54
55void SchedulingLatencyVisitorARM::VisitSub(HSub* instr) {
56 HandleBinaryOperationLantencies(instr);
57}
58
59void SchedulingLatencyVisitorARM::VisitMul(HMul* instr) {
60 switch (instr->GetResultType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010061 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +000062 last_visited_internal_latency_ = 3 * kArmMulIntegerLatency;
63 last_visited_latency_ = kArmIntegerOpLatency;
64 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010065 case DataType::Type::kFloat32:
66 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +000067 last_visited_latency_ = kArmMulFloatingPointLatency;
68 break;
69 default:
70 last_visited_latency_ = kArmMulIntegerLatency;
71 break;
72 }
73}
74
75void SchedulingLatencyVisitorARM::HandleBitwiseOperationLantencies(HBinaryOperation* instr) {
76 switch (instr->GetResultType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010077 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +000078 last_visited_internal_latency_ = kArmIntegerOpLatency;
79 last_visited_latency_ = kArmIntegerOpLatency;
80 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010081 case DataType::Type::kFloat32:
82 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +000083 last_visited_latency_ = kArmFloatingPointOpLatency;
84 break;
85 default:
86 last_visited_latency_ = kArmIntegerOpLatency;
87 break;
88 }
89}
90
91void SchedulingLatencyVisitorARM::VisitAnd(HAnd* instr) {
92 HandleBitwiseOperationLantencies(instr);
93}
94
95void SchedulingLatencyVisitorARM::VisitOr(HOr* instr) {
96 HandleBitwiseOperationLantencies(instr);
97}
98
99void SchedulingLatencyVisitorARM::VisitXor(HXor* instr) {
100 HandleBitwiseOperationLantencies(instr);
101}
102
103void SchedulingLatencyVisitorARM::VisitRor(HRor* instr) {
104 switch (instr->GetResultType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100105 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000106 last_visited_latency_ = kArmIntegerOpLatency;
107 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100108 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000109 // HandleLongRotate
110 HInstruction* rhs = instr->GetRight();
111 if (rhs->IsConstant()) {
112 uint64_t rot = Uint64ConstantFrom(rhs->AsConstant()) & kMaxLongShiftDistance;
113 if (rot != 0u) {
114 last_visited_internal_latency_ = 3 * kArmIntegerOpLatency;
115 last_visited_latency_ = kArmIntegerOpLatency;
116 } else {
117 last_visited_internal_latency_ = kArmIntegerOpLatency;
118 last_visited_latency_ = kArmIntegerOpLatency;
119 }
120 } else {
121 last_visited_internal_latency_ = 9 * kArmIntegerOpLatency + kArmBranchLatency;
122 last_visited_latency_ = kArmBranchLatency;
123 }
124 break;
125 }
126 default:
127 LOG(FATAL) << "Unexpected operation type " << instr->GetResultType();
128 UNREACHABLE();
129 }
130}
131
132void SchedulingLatencyVisitorARM::HandleShiftLatencies(HBinaryOperation* instr) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100133 DataType::Type type = instr->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000134 HInstruction* rhs = instr->GetRight();
135 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100136 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000137 if (!rhs->IsConstant()) {
138 last_visited_internal_latency_ = kArmIntegerOpLatency;
139 }
140 last_visited_latency_ = kArmIntegerOpLatency;
141 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100142 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000143 if (!rhs->IsConstant()) {
144 last_visited_internal_latency_ = 8 * kArmIntegerOpLatency;
145 } else {
146 uint32_t shift_value = Int32ConstantFrom(rhs->AsConstant()) & kMaxLongShiftDistance;
147 if (shift_value == 1 || shift_value >= 32) {
148 last_visited_internal_latency_ = kArmIntegerOpLatency;
149 } else {
150 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
151 }
152 }
153 last_visited_latency_ = kArmIntegerOpLatency;
154 break;
155 default:
156 LOG(FATAL) << "Unexpected operation type " << type;
157 UNREACHABLE();
158 }
159}
160
161void SchedulingLatencyVisitorARM::VisitShl(HShl* instr) {
162 HandleShiftLatencies(instr);
163}
164
165void SchedulingLatencyVisitorARM::VisitShr(HShr* instr) {
166 HandleShiftLatencies(instr);
167}
168
169void SchedulingLatencyVisitorARM::VisitUShr(HUShr* instr) {
170 HandleShiftLatencies(instr);
171}
172
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100173void SchedulingLatencyVisitorARM::HandleGenerateConditionWithZero(IfCondition condition) {
174 switch (condition) {
175 case kCondEQ:
176 case kCondBE:
177 case kCondNE:
178 case kCondA:
179 last_visited_internal_latency_ += kArmIntegerOpLatency;
180 last_visited_latency_ = kArmIntegerOpLatency;
xueliang.zhongf7caf682017-03-01 16:07:02 +0000181 break;
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100182 case kCondGE:
183 // Mvn
184 last_visited_internal_latency_ += kArmIntegerOpLatency;
185 FALLTHROUGH_INTENDED;
186 case kCondLT:
187 // Lsr
188 last_visited_latency_ = kArmIntegerOpLatency;
189 break;
190 case kCondAE:
191 // Trivially true.
192 // Mov
193 last_visited_latency_ = kArmIntegerOpLatency;
194 break;
195 case kCondB:
196 // Trivially false.
197 // Mov
198 last_visited_latency_ = kArmIntegerOpLatency;
xueliang.zhongf7caf682017-03-01 16:07:02 +0000199 break;
200 default:
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100201 LOG(FATAL) << "Unexpected condition " << condition;
202 UNREACHABLE();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000203 }
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100204}
205
206void SchedulingLatencyVisitorARM::HandleGenerateLongTestConstant(HCondition* condition) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100207 DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64);
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100208
209 IfCondition cond = condition->GetCondition();
210
211 HInstruction* right = condition->InputAt(1);
212
213 int64_t value = Uint64ConstantFrom(right);
214
215 // Comparisons against 0 are common enough, so codegen has special handling for them.
216 if (value == 0) {
217 switch (cond) {
218 case kCondNE:
219 case kCondA:
220 case kCondEQ:
221 case kCondBE:
222 // Orrs
223 last_visited_internal_latency_ += kArmIntegerOpLatency;
224 return;
225 case kCondLT:
226 case kCondGE:
227 // Cmp
228 last_visited_internal_latency_ += kArmIntegerOpLatency;
229 return;
230 case kCondB:
231 case kCondAE:
232 // Cmp
233 last_visited_internal_latency_ += kArmIntegerOpLatency;
234 return;
235 default:
236 break;
237 }
238 }
239
240 switch (cond) {
241 case kCondEQ:
242 case kCondNE:
243 case kCondB:
244 case kCondBE:
245 case kCondA:
246 case kCondAE: {
247 // Cmp, IT, Cmp
248 last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
249 break;
250 }
251 case kCondLE:
252 case kCondGT:
253 // Trivially true or false.
254 if (value == std::numeric_limits<int64_t>::max()) {
255 // Cmp
256 last_visited_internal_latency_ += kArmIntegerOpLatency;
257 break;
258 }
259 FALLTHROUGH_INTENDED;
260 case kCondGE:
261 case kCondLT: {
262 // Cmp, Sbcs
263 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
264 break;
265 }
266 default:
267 LOG(FATAL) << "Unreachable";
268 UNREACHABLE();
269 }
270}
271
272void SchedulingLatencyVisitorARM::HandleGenerateLongTest(HCondition* condition) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100273 DCHECK_EQ(condition->GetLeft()->GetType(), DataType::Type::kInt64);
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100274
275 IfCondition cond = condition->GetCondition();
276
277 switch (cond) {
278 case kCondEQ:
279 case kCondNE:
280 case kCondB:
281 case kCondBE:
282 case kCondA:
283 case kCondAE: {
284 // Cmp, IT, Cmp
285 last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
286 break;
287 }
288 case kCondLE:
289 case kCondGT:
290 case kCondGE:
291 case kCondLT: {
292 // Cmp, Sbcs
293 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
294 break;
295 }
296 default:
297 LOG(FATAL) << "Unreachable";
298 UNREACHABLE();
299 }
300}
301
302// The GenerateTest series of function all counted as internal latency.
303void SchedulingLatencyVisitorARM::HandleGenerateTest(HCondition* condition) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100304 const DataType::Type type = condition->GetLeft()->GetType();
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100305
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100306 if (type == DataType::Type::kInt64) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100307 condition->InputAt(1)->IsConstant()
308 ? HandleGenerateLongTestConstant(condition)
309 : HandleGenerateLongTest(condition);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100310 } else if (DataType::IsFloatingPointType(type)) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100311 // GenerateVcmp + Vmrs
312 last_visited_internal_latency_ += 2 * kArmFloatingPointOpLatency;
313 } else {
314 // Cmp
315 last_visited_internal_latency_ += kArmIntegerOpLatency;
316 }
317}
318
319bool SchedulingLatencyVisitorARM::CanGenerateTest(HCondition* condition) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100320 if (condition->GetLeft()->GetType() == DataType::Type::kInt64) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100321 HInstruction* right = condition->InputAt(1);
322
323 if (right->IsConstant()) {
324 IfCondition c = condition->GetCondition();
325 const uint64_t value = Uint64ConstantFrom(right);
326
327 if (c < kCondLT || c > kCondGE) {
328 if (value != 0) {
329 return false;
330 }
331 } else if (c == kCondLE || c == kCondGT) {
332 if (value < std::numeric_limits<int64_t>::max() &&
333 !codegen_->GetAssembler()->ShifterOperandCanHold(SBC, High32Bits(value + 1), kCcSet)) {
334 return false;
335 }
336 } else if (!codegen_->GetAssembler()->ShifterOperandCanHold(SBC, High32Bits(value), kCcSet)) {
337 return false;
338 }
339 }
340 }
341
342 return true;
343}
344
345void SchedulingLatencyVisitorARM::HandleGenerateConditionGeneric(HCondition* cond) {
346 HandleGenerateTest(cond);
347
348 // Unlike codegen pass, we cannot check 'out' register IsLow() here,
349 // because scheduling is before liveness(location builder) and register allocator,
350 // so we can only choose to follow one path of codegen by assuming otu.IsLow() is true.
351 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
xueliang.zhongf7caf682017-03-01 16:07:02 +0000352 last_visited_latency_ = kArmIntegerOpLatency;
353}
354
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100355void SchedulingLatencyVisitorARM::HandleGenerateEqualLong(HCondition* cond) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100356 DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64);
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100357
358 IfCondition condition = cond->GetCondition();
359
360 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
361
362 if (condition == kCondNE) {
363 // Orrs, IT, Mov
364 last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
365 } else {
366 last_visited_internal_latency_ += kArmIntegerOpLatency;
367 HandleGenerateConditionWithZero(condition);
368 }
369}
370
371void SchedulingLatencyVisitorARM::HandleGenerateLongComparesAndJumps() {
372 last_visited_internal_latency_ += 4 * kArmIntegerOpLatency;
373 last_visited_internal_latency_ += kArmBranchLatency;
374}
375
376void SchedulingLatencyVisitorARM::HandleGenerateConditionLong(HCondition* cond) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100377 DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64);
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100378
379 IfCondition condition = cond->GetCondition();
380 HInstruction* right = cond->InputAt(1);
381
382 if (right->IsConstant()) {
383 // Comparisons against 0 are common enough, so codegen has special handling for them.
384 if (Uint64ConstantFrom(right) == 0) {
385 switch (condition) {
386 case kCondNE:
387 case kCondA:
388 case kCondEQ:
389 case kCondBE:
390 // Orr
391 last_visited_internal_latency_ += kArmIntegerOpLatency;
392 HandleGenerateConditionWithZero(condition);
393 return;
394 case kCondLT:
395 case kCondGE:
396 FALLTHROUGH_INTENDED;
397 case kCondAE:
398 case kCondB:
399 HandleGenerateConditionWithZero(condition);
400 return;
401 case kCondLE:
402 case kCondGT:
403 default:
404 break;
405 }
406 }
407 }
408
409 if ((condition == kCondEQ || condition == kCondNE) &&
410 !CanGenerateTest(cond)) {
411 HandleGenerateEqualLong(cond);
412 return;
413 }
414
415 if (CanGenerateTest(cond)) {
416 HandleGenerateConditionGeneric(cond);
417 return;
418 }
419
420 HandleGenerateLongComparesAndJumps();
421
422 last_visited_internal_latency_ += kArmIntegerOpLatency;
423 last_visited_latency_ = kArmBranchLatency;;
424}
425
426void SchedulingLatencyVisitorARM::HandleGenerateConditionIntegralOrNonPrimitive(HCondition* cond) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100427 const DataType::Type type = cond->GetLeft()->GetType();
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100428
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100429 DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type;
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100430
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100431 if (type == DataType::Type::kInt64) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100432 HandleGenerateConditionLong(cond);
433 return;
434 }
435
436 IfCondition condition = cond->GetCondition();
437 HInstruction* right = cond->InputAt(1);
438 int64_t value;
439
440 if (right->IsConstant()) {
441 value = Uint64ConstantFrom(right);
442
443 // Comparisons against 0 are common enough, so codegen has special handling for them.
444 if (value == 0) {
445 switch (condition) {
446 case kCondNE:
447 case kCondA:
448 case kCondEQ:
449 case kCondBE:
450 case kCondLT:
451 case kCondGE:
452 case kCondAE:
453 case kCondB:
454 HandleGenerateConditionWithZero(condition);
455 return;
456 case kCondLE:
457 case kCondGT:
458 default:
459 break;
460 }
461 }
462 }
463
464 if (condition == kCondEQ || condition == kCondNE) {
465 if (condition == kCondNE) {
466 // CMP, IT, MOV.ne
467 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
468 last_visited_latency_ = kArmIntegerOpLatency;
469 } else {
470 last_visited_internal_latency_ += kArmIntegerOpLatency;
471 HandleGenerateConditionWithZero(condition);
472 }
473 return;
474 }
475
476 HandleGenerateConditionGeneric(cond);
477}
478
479void SchedulingLatencyVisitorARM::HandleCondition(HCondition* cond) {
480 if (cond->IsEmittedAtUseSite()) {
481 last_visited_latency_ = 0;
482 return;
483 }
484
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100485 const DataType::Type type = cond->GetLeft()->GetType();
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100486
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100487 if (DataType::IsFloatingPointType(type)) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100488 HandleGenerateConditionGeneric(cond);
489 return;
490 }
491
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100492 DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type;
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100493
494 const IfCondition condition = cond->GetCondition();
495
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100496 if (type == DataType::Type::kBool &&
497 cond->GetRight()->GetType() == DataType::Type::kBool &&
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100498 (condition == kCondEQ || condition == kCondNE)) {
499 if (condition == kCondEQ) {
500 last_visited_internal_latency_ = kArmIntegerOpLatency;
501 }
502 last_visited_latency_ = kArmIntegerOpLatency;
503 return;
504 }
505
506 HandleGenerateConditionIntegralOrNonPrimitive(cond);
507}
508
509void SchedulingLatencyVisitorARM::VisitCondition(HCondition* instr) {
510 HandleCondition(instr);
511}
512
xueliang.zhongf7caf682017-03-01 16:07:02 +0000513void SchedulingLatencyVisitorARM::VisitCompare(HCompare* instr) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100514 DataType::Type type = instr->InputAt(0)->GetType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000515 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100516 case DataType::Type::kBool:
517 case DataType::Type::kInt8:
518 case DataType::Type::kInt16:
519 case DataType::Type::kUint16:
520 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000521 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
522 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100523 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000524 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency + 3 * kArmBranchLatency;
525 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100526 case DataType::Type::kFloat32:
527 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000528 last_visited_internal_latency_ = kArmIntegerOpLatency + 2 * kArmFloatingPointOpLatency;
529 break;
530 default:
531 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
532 break;
533 }
534 last_visited_latency_ = kArmIntegerOpLatency;
535}
536
537void SchedulingLatencyVisitorARM::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100538 if (instruction->GetResultType() == DataType::Type::kInt32) {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000539 last_visited_latency_ = kArmIntegerOpLatency;
540 } else {
541 last_visited_internal_latency_ = kArmIntegerOpLatency;
542 last_visited_latency_ = kArmIntegerOpLatency;
543 }
544}
545
546void SchedulingLatencyVisitorARM::HandleGenerateDataProcInstruction(bool internal_latency) {
547 if (internal_latency) {
548 last_visited_internal_latency_ += kArmIntegerOpLatency;
549 } else {
550 last_visited_latency_ = kArmDataProcWithShifterOpLatency;
551 }
552}
553
554void SchedulingLatencyVisitorARM::HandleGenerateDataProc(HDataProcWithShifterOp* instruction) {
555 const HInstruction::InstructionKind kind = instruction->GetInstrKind();
556 if (kind == HInstruction::kAdd) {
557 last_visited_internal_latency_ = kArmIntegerOpLatency;
558 last_visited_latency_ = kArmIntegerOpLatency;
559 } else if (kind == HInstruction::kSub) {
560 last_visited_internal_latency_ = kArmIntegerOpLatency;
561 last_visited_latency_ = kArmIntegerOpLatency;
562 } else {
563 HandleGenerateDataProcInstruction(/* internal_latency */ true);
564 HandleGenerateDataProcInstruction();
565 }
566}
567
568void SchedulingLatencyVisitorARM::HandleGenerateLongDataProc(HDataProcWithShifterOp* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100569 DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
xueliang.zhongf7caf682017-03-01 16:07:02 +0000570 DCHECK(HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind()));
571
572 const uint32_t shift_value = instruction->GetShiftAmount();
573 const HInstruction::InstructionKind kind = instruction->GetInstrKind();
574
575 if (shift_value >= 32) {
576 // Different shift types actually generate similar code here,
577 // no need to differentiate shift types like the codegen pass does,
578 // which also avoids handling shift types from different ARM backends.
579 HandleGenerateDataProc(instruction);
580 } else {
581 DCHECK_GT(shift_value, 1U);
582 DCHECK_LT(shift_value, 32U);
583
584 if (kind == HInstruction::kOr || kind == HInstruction::kXor) {
585 HandleGenerateDataProcInstruction(/* internal_latency */ true);
586 HandleGenerateDataProcInstruction(/* internal_latency */ true);
587 HandleGenerateDataProcInstruction();
588 } else {
589 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
590 HandleGenerateDataProc(instruction);
591 }
592 }
593}
594
595void SchedulingLatencyVisitorARM::VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) {
596 const HDataProcWithShifterOp::OpKind op_kind = instruction->GetOpKind();
597
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100598 if (instruction->GetType() == DataType::Type::kInt32) {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000599 HandleGenerateDataProcInstruction();
600 } else {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100601 DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
xueliang.zhongf7caf682017-03-01 16:07:02 +0000602 if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) {
603 HandleGenerateDataProc(instruction);
604 } else {
605 HandleGenerateLongDataProc(instruction);
606 }
607 }
608}
609
610void SchedulingLatencyVisitorARM::VisitIntermediateAddress(HIntermediateAddress* ATTRIBUTE_UNUSED) {
611 // Although the code generated is a simple `add` instruction, we found through empirical results
612 // that spacing it from its use in memory accesses was beneficial.
613 last_visited_internal_latency_ = kArmNopLatency;
614 last_visited_latency_ = kArmIntegerOpLatency;
615}
616
Artem Serovf0fc4c62017-05-03 15:07:15 +0100617void SchedulingLatencyVisitorARM::VisitIntermediateAddressIndex(
618 HIntermediateAddressIndex* ATTRIBUTE_UNUSED) {
619 UNIMPLEMENTED(FATAL) << "IntermediateAddressIndex is not implemented for ARM";
620}
621
xueliang.zhongf7caf682017-03-01 16:07:02 +0000622void SchedulingLatencyVisitorARM::VisitMultiplyAccumulate(HMultiplyAccumulate* ATTRIBUTE_UNUSED) {
623 last_visited_latency_ = kArmMulIntegerLatency;
624}
625
626void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100627 DataType::Type type = instruction->GetType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000628 const bool maybe_compressed_char_at =
629 mirror::kUseStringCompression && instruction->IsStringCharAt();
630 HInstruction* array_instr = instruction->GetArray();
631 bool has_intermediate_address = array_instr->IsIntermediateAddress();
632 HInstruction* index = instruction->InputAt(1);
633
634 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100635 case DataType::Type::kBool:
636 case DataType::Type::kInt8:
637 case DataType::Type::kInt16:
638 case DataType::Type::kUint16:
639 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000640 if (maybe_compressed_char_at) {
641 last_visited_internal_latency_ += kArmMemoryLoadLatency;
642 }
643 if (index->IsConstant()) {
644 if (maybe_compressed_char_at) {
645 last_visited_internal_latency_ +=
646 kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
647 last_visited_latency_ = kArmBranchLatency;
648 } else {
649 last_visited_latency_ += kArmMemoryLoadLatency;
650 }
651 } else {
652 if (has_intermediate_address) {
653 } else {
654 last_visited_internal_latency_ += kArmIntegerOpLatency;
655 }
656 if (maybe_compressed_char_at) {
657 last_visited_internal_latency_ +=
658 kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
659 last_visited_latency_ = kArmBranchLatency;
660 } else {
661 last_visited_latency_ += kArmMemoryLoadLatency;
662 }
663 }
664 break;
665 }
666
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100667 case DataType::Type::kReference: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000668 if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
669 last_visited_latency_ = kArmLoadWithBakerReadBarrierLatency;
670 } else {
671 if (index->IsConstant()) {
672 last_visited_latency_ = kArmMemoryLoadLatency;
673 } else {
674 if (has_intermediate_address) {
675 } else {
676 last_visited_internal_latency_ += kArmIntegerOpLatency;
677 }
678 last_visited_internal_latency_ = kArmMemoryLoadLatency;
679 }
680 }
681 break;
682 }
683
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100684 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000685 if (index->IsConstant()) {
686 last_visited_latency_ = kArmMemoryLoadLatency;
687 } else {
688 last_visited_internal_latency_ += kArmIntegerOpLatency;
689 last_visited_latency_ = kArmMemoryLoadLatency;
690 }
691 break;
692 }
693
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100694 case DataType::Type::kFloat32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000695 if (index->IsConstant()) {
696 last_visited_latency_ = kArmMemoryLoadLatency;
697 } else {
698 last_visited_internal_latency_ += kArmIntegerOpLatency;
699 last_visited_latency_ = kArmMemoryLoadLatency;
700 }
701 break;
702 }
703
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100704 case DataType::Type::kFloat64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000705 if (index->IsConstant()) {
706 last_visited_latency_ = kArmMemoryLoadLatency;
707 } else {
708 last_visited_internal_latency_ += kArmIntegerOpLatency;
709 last_visited_latency_ = kArmMemoryLoadLatency;
710 }
711 break;
712 }
713
714 default:
715 LOG(FATAL) << "Unreachable type " << type;
716 UNREACHABLE();
717 }
718}
719
720void SchedulingLatencyVisitorARM::VisitArrayLength(HArrayLength* instruction) {
721 last_visited_latency_ = kArmMemoryLoadLatency;
722 if (mirror::kUseStringCompression && instruction->IsStringLength()) {
723 last_visited_internal_latency_ = kArmMemoryLoadLatency;
724 last_visited_latency_ = kArmIntegerOpLatency;
725 }
726}
727
728void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) {
729 HInstruction* index = instruction->InputAt(1);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100730 DataType::Type value_type = instruction->GetComponentType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000731 HInstruction* array_instr = instruction->GetArray();
732 bool has_intermediate_address = array_instr->IsIntermediateAddress();
733
734 switch (value_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100735 case DataType::Type::kBool:
736 case DataType::Type::kInt8:
737 case DataType::Type::kInt16:
738 case DataType::Type::kUint16:
739 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000740 if (index->IsConstant()) {
741 last_visited_latency_ = kArmMemoryStoreLatency;
742 } else {
743 if (has_intermediate_address) {
744 } else {
745 last_visited_internal_latency_ = kArmIntegerOpLatency;
746 }
747 last_visited_latency_ = kArmMemoryStoreLatency;
748 }
749 break;
750 }
751
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100752 case DataType::Type::kReference: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000753 if (instruction->InputAt(2)->IsNullConstant()) {
754 if (index->IsConstant()) {
755 last_visited_latency_ = kArmMemoryStoreLatency;
756 } else {
757 last_visited_internal_latency_ = kArmIntegerOpLatency;
758 last_visited_latency_ = kArmMemoryStoreLatency;
759 }
760 } else {
761 // Following the exact instructions of runtime type checks is too complicated,
762 // just giving it a simple slow latency.
763 last_visited_latency_ = kArmRuntimeTypeCheckLatency;
764 }
765 break;
766 }
767
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100768 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000769 if (index->IsConstant()) {
770 last_visited_latency_ = kArmMemoryLoadLatency;
771 } else {
772 last_visited_internal_latency_ = kArmIntegerOpLatency;
773 last_visited_latency_ = kArmMemoryLoadLatency;
774 }
775 break;
776 }
777
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100778 case DataType::Type::kFloat32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000779 if (index->IsConstant()) {
780 last_visited_latency_ = kArmMemoryLoadLatency;
781 } else {
782 last_visited_internal_latency_ = kArmIntegerOpLatency;
783 last_visited_latency_ = kArmMemoryLoadLatency;
784 }
785 break;
786 }
787
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100788 case DataType::Type::kFloat64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000789 if (index->IsConstant()) {
790 last_visited_latency_ = kArmMemoryLoadLatency;
791 } else {
792 last_visited_internal_latency_ = kArmIntegerOpLatency;
793 last_visited_latency_ = kArmMemoryLoadLatency;
794 }
795 break;
796 }
797
798 default:
799 LOG(FATAL) << "Unreachable type " << value_type;
800 UNREACHABLE();
801 }
802}
803
804void SchedulingLatencyVisitorARM::VisitBoundsCheck(HBoundsCheck* ATTRIBUTE_UNUSED) {
805 last_visited_internal_latency_ = kArmIntegerOpLatency;
806 // Users do not use any data results.
807 last_visited_latency_ = 0;
808}
809
810void SchedulingLatencyVisitorARM::HandleDivRemConstantIntegralLatencies(int32_t imm) {
811 if (imm == 0) {
812 last_visited_internal_latency_ = 0;
813 last_visited_latency_ = 0;
814 } else if (imm == 1 || imm == -1) {
815 last_visited_latency_ = kArmIntegerOpLatency;
816 } else if (IsPowerOfTwo(AbsOrMin(imm))) {
817 last_visited_internal_latency_ = 3 * kArmIntegerOpLatency;
818 last_visited_latency_ = kArmIntegerOpLatency;
819 } else {
820 last_visited_internal_latency_ = kArmMulIntegerLatency + 2 * kArmIntegerOpLatency;
821 last_visited_latency_ = kArmIntegerOpLatency;
822 }
823}
824
825void SchedulingLatencyVisitorARM::VisitDiv(HDiv* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100826 DataType::Type type = instruction->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000827 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100828 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000829 HInstruction* rhs = instruction->GetRight();
830 if (rhs->IsConstant()) {
831 int32_t imm = Int32ConstantFrom(rhs->AsConstant());
832 HandleDivRemConstantIntegralLatencies(imm);
833 } else {
834 last_visited_latency_ = kArmDivIntegerLatency;
835 }
836 break;
837 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100838 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000839 last_visited_latency_ = kArmDivFloatLatency;
840 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100841 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000842 last_visited_latency_ = kArmDivDoubleLatency;
843 break;
844 default:
845 last_visited_internal_latency_ = kArmCallInternalLatency;
846 last_visited_latency_ = kArmCallLatency;
847 break;
848 }
849}
850
851void SchedulingLatencyVisitorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
852 HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
853}
854
855void SchedulingLatencyVisitorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
856 HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
857}
858
859void SchedulingLatencyVisitorARM::VisitInstanceOf(HInstanceOf* ATTRIBUTE_UNUSED) {
860 last_visited_internal_latency_ = kArmCallInternalLatency;
861 last_visited_latency_ = kArmIntegerOpLatency;
862}
863
864void SchedulingLatencyVisitorARM::VisitInvoke(HInvoke* ATTRIBUTE_UNUSED) {
865 last_visited_internal_latency_ = kArmCallInternalLatency;
866 last_visited_latency_ = kArmCallLatency;
867}
868
869void SchedulingLatencyVisitorARM::VisitLoadString(HLoadString* ATTRIBUTE_UNUSED) {
870 last_visited_internal_latency_ = kArmLoadStringInternalLatency;
871 last_visited_latency_ = kArmMemoryLoadLatency;
872}
873
874void SchedulingLatencyVisitorARM::VisitNewArray(HNewArray* ATTRIBUTE_UNUSED) {
875 last_visited_internal_latency_ = kArmIntegerOpLatency + kArmCallInternalLatency;
876 last_visited_latency_ = kArmCallLatency;
877}
878
879void SchedulingLatencyVisitorARM::VisitNewInstance(HNewInstance* instruction) {
880 if (instruction->IsStringAlloc()) {
881 last_visited_internal_latency_ = 2 * kArmMemoryLoadLatency + kArmCallInternalLatency;
882 } else {
883 last_visited_internal_latency_ = kArmCallInternalLatency;
884 }
885 last_visited_latency_ = kArmCallLatency;
886}
887
888void SchedulingLatencyVisitorARM::VisitRem(HRem* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100889 DataType::Type type = instruction->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000890 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100891 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000892 HInstruction* rhs = instruction->GetRight();
893 if (rhs->IsConstant()) {
894 int32_t imm = Int32ConstantFrom(rhs->AsConstant());
895 HandleDivRemConstantIntegralLatencies(imm);
896 } else {
897 last_visited_internal_latency_ = kArmDivIntegerLatency;
898 last_visited_latency_ = kArmMulIntegerLatency;
899 }
900 break;
901 }
902 default:
903 last_visited_internal_latency_ = kArmCallInternalLatency;
904 last_visited_latency_ = kArmCallLatency;
905 break;
906 }
907}
908
909void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruction,
910 const FieldInfo& field_info) {
911 DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
912 DCHECK(codegen_ != nullptr);
913 bool is_volatile = field_info.IsVolatile();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100914 DataType::Type field_type = field_info.GetFieldType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000915 bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
916
917 switch (field_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100918 case DataType::Type::kBool:
919 case DataType::Type::kInt8:
920 case DataType::Type::kInt16:
921 case DataType::Type::kUint16:
922 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000923 last_visited_latency_ = kArmMemoryLoadLatency;
924 break;
925
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100926 case DataType::Type::kReference:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000927 if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
928 last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
929 last_visited_latency_ = kArmMemoryLoadLatency;
930 } else {
931 last_visited_latency_ = kArmMemoryLoadLatency;
932 }
933 break;
934
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100935 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000936 if (is_volatile && !atomic_ldrd_strd) {
937 last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
938 last_visited_latency_ = kArmMemoryLoadLatency;
939 } else {
940 last_visited_latency_ = kArmMemoryLoadLatency;
941 }
942 break;
943
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100944 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000945 last_visited_latency_ = kArmMemoryLoadLatency;
946 break;
947
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100948 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000949 if (is_volatile && !atomic_ldrd_strd) {
950 last_visited_internal_latency_ =
951 kArmMemoryLoadLatency + kArmIntegerOpLatency + kArmMemoryLoadLatency;
952 last_visited_latency_ = kArmIntegerOpLatency;
953 } else {
954 last_visited_latency_ = kArmMemoryLoadLatency;
955 }
956 break;
957
958 default:
959 last_visited_latency_ = kArmMemoryLoadLatency;
960 break;
961 }
962
963 if (is_volatile) {
964 last_visited_internal_latency_ += kArmMemoryBarrierLatency;
965 }
966}
967
968void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruction,
969 const FieldInfo& field_info) {
970 DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
971 DCHECK(codegen_ != nullptr);
972 bool is_volatile = field_info.IsVolatile();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100973 DataType::Type field_type = field_info.GetFieldType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000974 bool needs_write_barrier =
975 CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
976 bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
977
978 switch (field_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100979 case DataType::Type::kBool:
980 case DataType::Type::kInt8:
981 case DataType::Type::kInt16:
982 case DataType::Type::kUint16:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000983 if (is_volatile) {
984 last_visited_internal_latency_ = kArmMemoryBarrierLatency + kArmMemoryStoreLatency;
985 last_visited_latency_ = kArmMemoryBarrierLatency;
986 } else {
987 last_visited_latency_ = kArmMemoryStoreLatency;
988 }
989 break;
990
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100991 case DataType::Type::kInt32:
992 case DataType::Type::kReference:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000993 if (kPoisonHeapReferences && needs_write_barrier) {
994 last_visited_internal_latency_ += kArmIntegerOpLatency * 2;
995 }
996 last_visited_latency_ = kArmMemoryStoreLatency;
997 break;
998
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100999 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001000 if (is_volatile && !atomic_ldrd_strd) {
1001 last_visited_internal_latency_ =
1002 kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1003 last_visited_latency_ = kArmIntegerOpLatency;
1004 } else {
1005 last_visited_latency_ = kArmMemoryStoreLatency;
1006 }
1007 break;
1008
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001009 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001010 last_visited_latency_ = kArmMemoryStoreLatency;
1011 break;
1012
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001013 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001014 if (is_volatile && !atomic_ldrd_strd) {
1015 last_visited_internal_latency_ = kArmIntegerOpLatency +
1016 kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1017 last_visited_latency_ = kArmIntegerOpLatency;
1018 } else {
1019 last_visited_latency_ = kArmMemoryStoreLatency;
1020 }
1021 break;
1022
1023 default:
1024 last_visited_latency_ = kArmMemoryStoreLatency;
1025 break;
1026 }
1027}
1028
1029void SchedulingLatencyVisitorARM::VisitStaticFieldGet(HStaticFieldGet* instruction) {
1030 HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
1031}
1032
1033void SchedulingLatencyVisitorARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
1034 HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
1035}
1036
1037void SchedulingLatencyVisitorARM::VisitSuspendCheck(HSuspendCheck* instruction) {
1038 HBasicBlock* block = instruction->GetBlock();
1039 DCHECK((block->GetLoopInformation() != nullptr) ||
1040 (block->IsEntryBlock() && instruction->GetNext()->IsGoto()));
1041 // Users do not use any data results.
1042 last_visited_latency_ = 0;
1043}
1044
1045void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001046 DataType::Type result_type = instr->GetResultType();
1047 DataType::Type input_type = instr->GetInputType();
xueliang.zhongf7caf682017-03-01 16:07:02 +00001048
1049 switch (result_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001050 case DataType::Type::kInt8:
1051 case DataType::Type::kUint16:
1052 case DataType::Type::kInt16:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001053 last_visited_latency_ = kArmIntegerOpLatency; // SBFX or UBFX
1054 break;
1055
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001056 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001057 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001058 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001059 last_visited_latency_ = kArmIntegerOpLatency; // MOV
1060 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001061 case DataType::Type::kFloat32:
1062 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001063 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1064 last_visited_latency_ = kArmFloatingPointOpLatency;
1065 break;
1066 default:
1067 last_visited_latency_ = kArmIntegerOpLatency;
1068 break;
1069 }
1070 break;
1071
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001072 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001073 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001074 case DataType::Type::kBool:
1075 case DataType::Type::kInt8:
1076 case DataType::Type::kUint16:
1077 case DataType::Type::kInt16:
1078 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001079 // MOV and extension
1080 last_visited_internal_latency_ = kArmIntegerOpLatency;
1081 last_visited_latency_ = kArmIntegerOpLatency;
1082 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001083 case DataType::Type::kFloat32:
1084 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001085 // invokes runtime
1086 last_visited_internal_latency_ = kArmCallInternalLatency;
1087 break;
1088 default:
1089 last_visited_internal_latency_ = kArmIntegerOpLatency;
1090 last_visited_latency_ = kArmIntegerOpLatency;
1091 break;
1092 }
1093 break;
1094
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001095 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001096 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001097 case DataType::Type::kBool:
1098 case DataType::Type::kInt8:
1099 case DataType::Type::kUint16:
1100 case DataType::Type::kInt16:
1101 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001102 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1103 last_visited_latency_ = kArmFloatingPointOpLatency;
1104 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001105 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001106 // invokes runtime
1107 last_visited_internal_latency_ = kArmCallInternalLatency;
1108 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001109 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001110 last_visited_latency_ = kArmFloatingPointOpLatency;
1111 break;
1112 default:
1113 last_visited_latency_ = kArmFloatingPointOpLatency;
1114 break;
1115 }
1116 break;
1117
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001118 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001119 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001120 case DataType::Type::kBool:
1121 case DataType::Type::kInt8:
1122 case DataType::Type::kUint16:
1123 case DataType::Type::kInt16:
1124 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001125 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1126 last_visited_latency_ = kArmFloatingPointOpLatency;
1127 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001128 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001129 last_visited_internal_latency_ = 5 * kArmFloatingPointOpLatency;
1130 last_visited_latency_ = kArmFloatingPointOpLatency;
1131 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001132 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001133 last_visited_latency_ = kArmFloatingPointOpLatency;
1134 break;
1135 default:
1136 last_visited_latency_ = kArmFloatingPointOpLatency;
1137 break;
1138 }
1139 break;
1140
1141 default:
1142 last_visited_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1143 break;
1144 }
1145}
1146
xueliang.zhongf7caf682017-03-01 16:07:02 +00001147} // namespace arm
1148} // namespace art