blob: 8dcadaad2ead1fbbbe9f8366bd7b491868580586 [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() &&
Vladimir Markof0a6a1d2018-01-08 14:23:56 +0000333 !codegen_->GetAssembler()->ShifterOperandCanHold(
334 SBC, High32Bits(value + 1), vixl32::FlagsUpdate::SetFlags)) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100335 return false;
336 }
Vladimir Markof0a6a1d2018-01-08 14:23:56 +0000337 } else if (!codegen_->GetAssembler()->ShifterOperandCanHold(
338 SBC, High32Bits(value), vixl32::FlagsUpdate::SetFlags)) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100339 return false;
340 }
341 }
342 }
343
344 return true;
345}
346
347void SchedulingLatencyVisitorARM::HandleGenerateConditionGeneric(HCondition* cond) {
348 HandleGenerateTest(cond);
349
350 // Unlike codegen pass, we cannot check 'out' register IsLow() here,
351 // because scheduling is before liveness(location builder) and register allocator,
352 // so we can only choose to follow one path of codegen by assuming otu.IsLow() is true.
353 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
xueliang.zhongf7caf682017-03-01 16:07:02 +0000354 last_visited_latency_ = kArmIntegerOpLatency;
355}
356
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100357void SchedulingLatencyVisitorARM::HandleGenerateEqualLong(HCondition* cond) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100358 DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64);
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100359
360 IfCondition condition = cond->GetCondition();
361
362 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
363
364 if (condition == kCondNE) {
365 // Orrs, IT, Mov
366 last_visited_internal_latency_ += 3 * kArmIntegerOpLatency;
367 } else {
368 last_visited_internal_latency_ += kArmIntegerOpLatency;
369 HandleGenerateConditionWithZero(condition);
370 }
371}
372
373void SchedulingLatencyVisitorARM::HandleGenerateLongComparesAndJumps() {
374 last_visited_internal_latency_ += 4 * kArmIntegerOpLatency;
375 last_visited_internal_latency_ += kArmBranchLatency;
376}
377
378void SchedulingLatencyVisitorARM::HandleGenerateConditionLong(HCondition* cond) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100379 DCHECK_EQ(cond->GetLeft()->GetType(), DataType::Type::kInt64);
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100380
381 IfCondition condition = cond->GetCondition();
382 HInstruction* right = cond->InputAt(1);
383
384 if (right->IsConstant()) {
385 // Comparisons against 0 are common enough, so codegen has special handling for them.
386 if (Uint64ConstantFrom(right) == 0) {
387 switch (condition) {
388 case kCondNE:
389 case kCondA:
390 case kCondEQ:
391 case kCondBE:
392 // Orr
393 last_visited_internal_latency_ += kArmIntegerOpLatency;
394 HandleGenerateConditionWithZero(condition);
395 return;
396 case kCondLT:
397 case kCondGE:
398 FALLTHROUGH_INTENDED;
399 case kCondAE:
400 case kCondB:
401 HandleGenerateConditionWithZero(condition);
402 return;
403 case kCondLE:
404 case kCondGT:
405 default:
406 break;
407 }
408 }
409 }
410
411 if ((condition == kCondEQ || condition == kCondNE) &&
412 !CanGenerateTest(cond)) {
413 HandleGenerateEqualLong(cond);
414 return;
415 }
416
417 if (CanGenerateTest(cond)) {
418 HandleGenerateConditionGeneric(cond);
419 return;
420 }
421
422 HandleGenerateLongComparesAndJumps();
423
424 last_visited_internal_latency_ += kArmIntegerOpLatency;
425 last_visited_latency_ = kArmBranchLatency;;
426}
427
428void SchedulingLatencyVisitorARM::HandleGenerateConditionIntegralOrNonPrimitive(HCondition* cond) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100429 const DataType::Type type = cond->GetLeft()->GetType();
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100430
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100431 DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type;
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100432
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100433 if (type == DataType::Type::kInt64) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100434 HandleGenerateConditionLong(cond);
435 return;
436 }
437
438 IfCondition condition = cond->GetCondition();
439 HInstruction* right = cond->InputAt(1);
440 int64_t value;
441
442 if (right->IsConstant()) {
443 value = Uint64ConstantFrom(right);
444
445 // Comparisons against 0 are common enough, so codegen has special handling for them.
446 if (value == 0) {
447 switch (condition) {
448 case kCondNE:
449 case kCondA:
450 case kCondEQ:
451 case kCondBE:
452 case kCondLT:
453 case kCondGE:
454 case kCondAE:
455 case kCondB:
456 HandleGenerateConditionWithZero(condition);
457 return;
458 case kCondLE:
459 case kCondGT:
460 default:
461 break;
462 }
463 }
464 }
465
466 if (condition == kCondEQ || condition == kCondNE) {
467 if (condition == kCondNE) {
468 // CMP, IT, MOV.ne
469 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
470 last_visited_latency_ = kArmIntegerOpLatency;
471 } else {
472 last_visited_internal_latency_ += kArmIntegerOpLatency;
473 HandleGenerateConditionWithZero(condition);
474 }
475 return;
476 }
477
478 HandleGenerateConditionGeneric(cond);
479}
480
481void SchedulingLatencyVisitorARM::HandleCondition(HCondition* cond) {
482 if (cond->IsEmittedAtUseSite()) {
483 last_visited_latency_ = 0;
484 return;
485 }
486
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100487 const DataType::Type type = cond->GetLeft()->GetType();
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100488
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100489 if (DataType::IsFloatingPointType(type)) {
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100490 HandleGenerateConditionGeneric(cond);
491 return;
492 }
493
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100494 DCHECK(DataType::IsIntegralType(type) || type == DataType::Type::kReference) << type;
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100495
496 const IfCondition condition = cond->GetCondition();
497
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100498 if (type == DataType::Type::kBool &&
499 cond->GetRight()->GetType() == DataType::Type::kBool &&
xueliang.zhongbf9e21a2017-06-15 11:01:11 +0100500 (condition == kCondEQ || condition == kCondNE)) {
501 if (condition == kCondEQ) {
502 last_visited_internal_latency_ = kArmIntegerOpLatency;
503 }
504 last_visited_latency_ = kArmIntegerOpLatency;
505 return;
506 }
507
508 HandleGenerateConditionIntegralOrNonPrimitive(cond);
509}
510
511void SchedulingLatencyVisitorARM::VisitCondition(HCondition* instr) {
512 HandleCondition(instr);
513}
514
xueliang.zhongf7caf682017-03-01 16:07:02 +0000515void SchedulingLatencyVisitorARM::VisitCompare(HCompare* instr) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100516 DataType::Type type = instr->InputAt(0)->GetType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000517 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100518 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100519 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100520 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100521 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100522 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100523 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000524 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
525 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100526 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000527 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency + 3 * kArmBranchLatency;
528 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100529 case DataType::Type::kFloat32:
530 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000531 last_visited_internal_latency_ = kArmIntegerOpLatency + 2 * kArmFloatingPointOpLatency;
532 break;
533 default:
534 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
535 break;
536 }
537 last_visited_latency_ = kArmIntegerOpLatency;
538}
539
540void SchedulingLatencyVisitorARM::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100541 if (instruction->GetResultType() == DataType::Type::kInt32) {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000542 last_visited_latency_ = kArmIntegerOpLatency;
543 } else {
544 last_visited_internal_latency_ = kArmIntegerOpLatency;
545 last_visited_latency_ = kArmIntegerOpLatency;
546 }
547}
548
549void SchedulingLatencyVisitorARM::HandleGenerateDataProcInstruction(bool internal_latency) {
550 if (internal_latency) {
551 last_visited_internal_latency_ += kArmIntegerOpLatency;
552 } else {
553 last_visited_latency_ = kArmDataProcWithShifterOpLatency;
554 }
555}
556
557void SchedulingLatencyVisitorARM::HandleGenerateDataProc(HDataProcWithShifterOp* instruction) {
558 const HInstruction::InstructionKind kind = instruction->GetInstrKind();
559 if (kind == HInstruction::kAdd) {
560 last_visited_internal_latency_ = kArmIntegerOpLatency;
561 last_visited_latency_ = kArmIntegerOpLatency;
562 } else if (kind == HInstruction::kSub) {
563 last_visited_internal_latency_ = kArmIntegerOpLatency;
564 last_visited_latency_ = kArmIntegerOpLatency;
565 } else {
566 HandleGenerateDataProcInstruction(/* internal_latency */ true);
567 HandleGenerateDataProcInstruction();
568 }
569}
570
571void SchedulingLatencyVisitorARM::HandleGenerateLongDataProc(HDataProcWithShifterOp* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100572 DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
xueliang.zhongf7caf682017-03-01 16:07:02 +0000573 DCHECK(HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind()));
574
575 const uint32_t shift_value = instruction->GetShiftAmount();
576 const HInstruction::InstructionKind kind = instruction->GetInstrKind();
577
578 if (shift_value >= 32) {
579 // Different shift types actually generate similar code here,
580 // no need to differentiate shift types like the codegen pass does,
581 // which also avoids handling shift types from different ARM backends.
582 HandleGenerateDataProc(instruction);
583 } else {
584 DCHECK_GT(shift_value, 1U);
585 DCHECK_LT(shift_value, 32U);
586
587 if (kind == HInstruction::kOr || kind == HInstruction::kXor) {
588 HandleGenerateDataProcInstruction(/* internal_latency */ true);
589 HandleGenerateDataProcInstruction(/* internal_latency */ true);
590 HandleGenerateDataProcInstruction();
591 } else {
592 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
593 HandleGenerateDataProc(instruction);
594 }
595 }
596}
597
598void SchedulingLatencyVisitorARM::VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) {
599 const HDataProcWithShifterOp::OpKind op_kind = instruction->GetOpKind();
600
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100601 if (instruction->GetType() == DataType::Type::kInt32) {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000602 HandleGenerateDataProcInstruction();
603 } else {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100604 DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
xueliang.zhongf7caf682017-03-01 16:07:02 +0000605 if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) {
606 HandleGenerateDataProc(instruction);
607 } else {
608 HandleGenerateLongDataProc(instruction);
609 }
610 }
611}
612
613void SchedulingLatencyVisitorARM::VisitIntermediateAddress(HIntermediateAddress* ATTRIBUTE_UNUSED) {
614 // Although the code generated is a simple `add` instruction, we found through empirical results
615 // that spacing it from its use in memory accesses was beneficial.
616 last_visited_internal_latency_ = kArmNopLatency;
617 last_visited_latency_ = kArmIntegerOpLatency;
618}
619
Artem Serovf0fc4c62017-05-03 15:07:15 +0100620void SchedulingLatencyVisitorARM::VisitIntermediateAddressIndex(
621 HIntermediateAddressIndex* ATTRIBUTE_UNUSED) {
622 UNIMPLEMENTED(FATAL) << "IntermediateAddressIndex is not implemented for ARM";
623}
624
xueliang.zhongf7caf682017-03-01 16:07:02 +0000625void SchedulingLatencyVisitorARM::VisitMultiplyAccumulate(HMultiplyAccumulate* ATTRIBUTE_UNUSED) {
626 last_visited_latency_ = kArmMulIntegerLatency;
627}
628
629void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100630 DataType::Type type = instruction->GetType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000631 const bool maybe_compressed_char_at =
632 mirror::kUseStringCompression && instruction->IsStringCharAt();
633 HInstruction* array_instr = instruction->GetArray();
634 bool has_intermediate_address = array_instr->IsIntermediateAddress();
635 HInstruction* index = instruction->InputAt(1);
636
637 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100638 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100639 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100640 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100641 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100642 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100643 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000644 if (maybe_compressed_char_at) {
645 last_visited_internal_latency_ += kArmMemoryLoadLatency;
646 }
647 if (index->IsConstant()) {
648 if (maybe_compressed_char_at) {
649 last_visited_internal_latency_ +=
650 kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
651 last_visited_latency_ = kArmBranchLatency;
652 } else {
653 last_visited_latency_ += kArmMemoryLoadLatency;
654 }
655 } else {
656 if (has_intermediate_address) {
657 } else {
658 last_visited_internal_latency_ += kArmIntegerOpLatency;
659 }
660 if (maybe_compressed_char_at) {
661 last_visited_internal_latency_ +=
662 kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
663 last_visited_latency_ = kArmBranchLatency;
664 } else {
665 last_visited_latency_ += kArmMemoryLoadLatency;
666 }
667 }
668 break;
669 }
670
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100671 case DataType::Type::kReference: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000672 if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
673 last_visited_latency_ = kArmLoadWithBakerReadBarrierLatency;
674 } else {
675 if (index->IsConstant()) {
676 last_visited_latency_ = kArmMemoryLoadLatency;
677 } else {
678 if (has_intermediate_address) {
679 } else {
680 last_visited_internal_latency_ += kArmIntegerOpLatency;
681 }
682 last_visited_internal_latency_ = kArmMemoryLoadLatency;
683 }
684 }
685 break;
686 }
687
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100688 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000689 if (index->IsConstant()) {
690 last_visited_latency_ = kArmMemoryLoadLatency;
691 } else {
692 last_visited_internal_latency_ += kArmIntegerOpLatency;
693 last_visited_latency_ = kArmMemoryLoadLatency;
694 }
695 break;
696 }
697
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100698 case DataType::Type::kFloat32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000699 if (index->IsConstant()) {
700 last_visited_latency_ = kArmMemoryLoadLatency;
701 } else {
702 last_visited_internal_latency_ += kArmIntegerOpLatency;
703 last_visited_latency_ = kArmMemoryLoadLatency;
704 }
705 break;
706 }
707
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100708 case DataType::Type::kFloat64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000709 if (index->IsConstant()) {
710 last_visited_latency_ = kArmMemoryLoadLatency;
711 } else {
712 last_visited_internal_latency_ += kArmIntegerOpLatency;
713 last_visited_latency_ = kArmMemoryLoadLatency;
714 }
715 break;
716 }
717
718 default:
719 LOG(FATAL) << "Unreachable type " << type;
720 UNREACHABLE();
721 }
722}
723
724void SchedulingLatencyVisitorARM::VisitArrayLength(HArrayLength* instruction) {
725 last_visited_latency_ = kArmMemoryLoadLatency;
726 if (mirror::kUseStringCompression && instruction->IsStringLength()) {
727 last_visited_internal_latency_ = kArmMemoryLoadLatency;
728 last_visited_latency_ = kArmIntegerOpLatency;
729 }
730}
731
732void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) {
733 HInstruction* index = instruction->InputAt(1);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100734 DataType::Type value_type = instruction->GetComponentType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000735 HInstruction* array_instr = instruction->GetArray();
736 bool has_intermediate_address = array_instr->IsIntermediateAddress();
737
738 switch (value_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100739 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100740 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100741 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100742 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100743 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100744 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000745 if (index->IsConstant()) {
746 last_visited_latency_ = kArmMemoryStoreLatency;
747 } else {
748 if (has_intermediate_address) {
749 } else {
750 last_visited_internal_latency_ = kArmIntegerOpLatency;
751 }
752 last_visited_latency_ = kArmMemoryStoreLatency;
753 }
754 break;
755 }
756
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100757 case DataType::Type::kReference: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000758 if (instruction->InputAt(2)->IsNullConstant()) {
759 if (index->IsConstant()) {
760 last_visited_latency_ = kArmMemoryStoreLatency;
761 } else {
762 last_visited_internal_latency_ = kArmIntegerOpLatency;
763 last_visited_latency_ = kArmMemoryStoreLatency;
764 }
765 } else {
766 // Following the exact instructions of runtime type checks is too complicated,
767 // just giving it a simple slow latency.
768 last_visited_latency_ = kArmRuntimeTypeCheckLatency;
769 }
770 break;
771 }
772
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100773 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000774 if (index->IsConstant()) {
775 last_visited_latency_ = kArmMemoryLoadLatency;
776 } else {
777 last_visited_internal_latency_ = kArmIntegerOpLatency;
778 last_visited_latency_ = kArmMemoryLoadLatency;
779 }
780 break;
781 }
782
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100783 case DataType::Type::kFloat32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000784 if (index->IsConstant()) {
785 last_visited_latency_ = kArmMemoryLoadLatency;
786 } else {
787 last_visited_internal_latency_ = kArmIntegerOpLatency;
788 last_visited_latency_ = kArmMemoryLoadLatency;
789 }
790 break;
791 }
792
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100793 case DataType::Type::kFloat64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000794 if (index->IsConstant()) {
795 last_visited_latency_ = kArmMemoryLoadLatency;
796 } else {
797 last_visited_internal_latency_ = kArmIntegerOpLatency;
798 last_visited_latency_ = kArmMemoryLoadLatency;
799 }
800 break;
801 }
802
803 default:
804 LOG(FATAL) << "Unreachable type " << value_type;
805 UNREACHABLE();
806 }
807}
808
809void SchedulingLatencyVisitorARM::VisitBoundsCheck(HBoundsCheck* ATTRIBUTE_UNUSED) {
810 last_visited_internal_latency_ = kArmIntegerOpLatency;
811 // Users do not use any data results.
812 last_visited_latency_ = 0;
813}
814
815void SchedulingLatencyVisitorARM::HandleDivRemConstantIntegralLatencies(int32_t imm) {
816 if (imm == 0) {
817 last_visited_internal_latency_ = 0;
818 last_visited_latency_ = 0;
819 } else if (imm == 1 || imm == -1) {
820 last_visited_latency_ = kArmIntegerOpLatency;
821 } else if (IsPowerOfTwo(AbsOrMin(imm))) {
822 last_visited_internal_latency_ = 3 * kArmIntegerOpLatency;
823 last_visited_latency_ = kArmIntegerOpLatency;
824 } else {
825 last_visited_internal_latency_ = kArmMulIntegerLatency + 2 * kArmIntegerOpLatency;
826 last_visited_latency_ = kArmIntegerOpLatency;
827 }
828}
829
830void SchedulingLatencyVisitorARM::VisitDiv(HDiv* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100831 DataType::Type type = instruction->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000832 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100833 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000834 HInstruction* rhs = instruction->GetRight();
835 if (rhs->IsConstant()) {
836 int32_t imm = Int32ConstantFrom(rhs->AsConstant());
837 HandleDivRemConstantIntegralLatencies(imm);
838 } else {
839 last_visited_latency_ = kArmDivIntegerLatency;
840 }
841 break;
842 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100843 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000844 last_visited_latency_ = kArmDivFloatLatency;
845 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100846 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000847 last_visited_latency_ = kArmDivDoubleLatency;
848 break;
849 default:
850 last_visited_internal_latency_ = kArmCallInternalLatency;
851 last_visited_latency_ = kArmCallLatency;
852 break;
853 }
854}
855
856void SchedulingLatencyVisitorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
857 HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
858}
859
860void SchedulingLatencyVisitorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
861 HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
862}
863
864void SchedulingLatencyVisitorARM::VisitInstanceOf(HInstanceOf* ATTRIBUTE_UNUSED) {
865 last_visited_internal_latency_ = kArmCallInternalLatency;
866 last_visited_latency_ = kArmIntegerOpLatency;
867}
868
869void SchedulingLatencyVisitorARM::VisitInvoke(HInvoke* ATTRIBUTE_UNUSED) {
870 last_visited_internal_latency_ = kArmCallInternalLatency;
871 last_visited_latency_ = kArmCallLatency;
872}
873
874void SchedulingLatencyVisitorARM::VisitLoadString(HLoadString* ATTRIBUTE_UNUSED) {
875 last_visited_internal_latency_ = kArmLoadStringInternalLatency;
876 last_visited_latency_ = kArmMemoryLoadLatency;
877}
878
879void SchedulingLatencyVisitorARM::VisitNewArray(HNewArray* ATTRIBUTE_UNUSED) {
880 last_visited_internal_latency_ = kArmIntegerOpLatency + kArmCallInternalLatency;
881 last_visited_latency_ = kArmCallLatency;
882}
883
884void SchedulingLatencyVisitorARM::VisitNewInstance(HNewInstance* instruction) {
885 if (instruction->IsStringAlloc()) {
886 last_visited_internal_latency_ = 2 * kArmMemoryLoadLatency + kArmCallInternalLatency;
887 } else {
888 last_visited_internal_latency_ = kArmCallInternalLatency;
889 }
890 last_visited_latency_ = kArmCallLatency;
891}
892
893void SchedulingLatencyVisitorARM::VisitRem(HRem* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100894 DataType::Type type = instruction->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000895 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100896 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000897 HInstruction* rhs = instruction->GetRight();
898 if (rhs->IsConstant()) {
899 int32_t imm = Int32ConstantFrom(rhs->AsConstant());
900 HandleDivRemConstantIntegralLatencies(imm);
901 } else {
902 last_visited_internal_latency_ = kArmDivIntegerLatency;
903 last_visited_latency_ = kArmMulIntegerLatency;
904 }
905 break;
906 }
907 default:
908 last_visited_internal_latency_ = kArmCallInternalLatency;
909 last_visited_latency_ = kArmCallLatency;
910 break;
911 }
912}
913
914void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruction,
915 const FieldInfo& field_info) {
916 DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
917 DCHECK(codegen_ != nullptr);
918 bool is_volatile = field_info.IsVolatile();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100919 DataType::Type field_type = field_info.GetFieldType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000920 bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
921
922 switch (field_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100923 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100924 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100925 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100926 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100927 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100928 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000929 last_visited_latency_ = kArmMemoryLoadLatency;
930 break;
931
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100932 case DataType::Type::kReference:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000933 if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
934 last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
935 last_visited_latency_ = kArmMemoryLoadLatency;
936 } else {
937 last_visited_latency_ = kArmMemoryLoadLatency;
938 }
939 break;
940
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100941 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000942 if (is_volatile && !atomic_ldrd_strd) {
943 last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
944 last_visited_latency_ = kArmMemoryLoadLatency;
945 } else {
946 last_visited_latency_ = kArmMemoryLoadLatency;
947 }
948 break;
949
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100950 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000951 last_visited_latency_ = kArmMemoryLoadLatency;
952 break;
953
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100954 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000955 if (is_volatile && !atomic_ldrd_strd) {
956 last_visited_internal_latency_ =
957 kArmMemoryLoadLatency + kArmIntegerOpLatency + kArmMemoryLoadLatency;
958 last_visited_latency_ = kArmIntegerOpLatency;
959 } else {
960 last_visited_latency_ = kArmMemoryLoadLatency;
961 }
962 break;
963
964 default:
965 last_visited_latency_ = kArmMemoryLoadLatency;
966 break;
967 }
968
969 if (is_volatile) {
970 last_visited_internal_latency_ += kArmMemoryBarrierLatency;
971 }
972}
973
974void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruction,
975 const FieldInfo& field_info) {
976 DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
977 DCHECK(codegen_ != nullptr);
978 bool is_volatile = field_info.IsVolatile();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100979 DataType::Type field_type = field_info.GetFieldType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000980 bool needs_write_barrier =
981 CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
982 bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
983
984 switch (field_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100985 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100986 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100987 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100988 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100989 case DataType::Type::kInt16:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000990 if (is_volatile) {
991 last_visited_internal_latency_ = kArmMemoryBarrierLatency + kArmMemoryStoreLatency;
992 last_visited_latency_ = kArmMemoryBarrierLatency;
993 } else {
994 last_visited_latency_ = kArmMemoryStoreLatency;
995 }
996 break;
997
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100998 case DataType::Type::kInt32:
999 case DataType::Type::kReference:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001000 if (kPoisonHeapReferences && needs_write_barrier) {
1001 last_visited_internal_latency_ += kArmIntegerOpLatency * 2;
1002 }
1003 last_visited_latency_ = kArmMemoryStoreLatency;
1004 break;
1005
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001006 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001007 if (is_volatile && !atomic_ldrd_strd) {
1008 last_visited_internal_latency_ =
1009 kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1010 last_visited_latency_ = kArmIntegerOpLatency;
1011 } else {
1012 last_visited_latency_ = kArmMemoryStoreLatency;
1013 }
1014 break;
1015
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001016 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001017 last_visited_latency_ = kArmMemoryStoreLatency;
1018 break;
1019
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001020 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001021 if (is_volatile && !atomic_ldrd_strd) {
1022 last_visited_internal_latency_ = kArmIntegerOpLatency +
1023 kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1024 last_visited_latency_ = kArmIntegerOpLatency;
1025 } else {
1026 last_visited_latency_ = kArmMemoryStoreLatency;
1027 }
1028 break;
1029
1030 default:
1031 last_visited_latency_ = kArmMemoryStoreLatency;
1032 break;
1033 }
1034}
1035
1036void SchedulingLatencyVisitorARM::VisitStaticFieldGet(HStaticFieldGet* instruction) {
1037 HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
1038}
1039
1040void SchedulingLatencyVisitorARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
1041 HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
1042}
1043
1044void SchedulingLatencyVisitorARM::VisitSuspendCheck(HSuspendCheck* instruction) {
1045 HBasicBlock* block = instruction->GetBlock();
1046 DCHECK((block->GetLoopInformation() != nullptr) ||
1047 (block->IsEntryBlock() && instruction->GetNext()->IsGoto()));
1048 // Users do not use any data results.
1049 last_visited_latency_ = 0;
1050}
1051
1052void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001053 DataType::Type result_type = instr->GetResultType();
1054 DataType::Type input_type = instr->GetInputType();
xueliang.zhongf7caf682017-03-01 16:07:02 +00001055
1056 switch (result_type) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001057 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001058 case DataType::Type::kInt8:
1059 case DataType::Type::kUint16:
1060 case DataType::Type::kInt16:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001061 last_visited_latency_ = kArmIntegerOpLatency; // SBFX or UBFX
1062 break;
1063
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001064 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001065 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001066 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001067 last_visited_latency_ = kArmIntegerOpLatency; // MOV
1068 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001069 case DataType::Type::kFloat32:
1070 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001071 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1072 last_visited_latency_ = kArmFloatingPointOpLatency;
1073 break;
1074 default:
1075 last_visited_latency_ = kArmIntegerOpLatency;
1076 break;
1077 }
1078 break;
1079
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001080 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001081 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001082 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001083 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001084 case DataType::Type::kInt8:
1085 case DataType::Type::kUint16:
1086 case DataType::Type::kInt16:
1087 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001088 // MOV and extension
1089 last_visited_internal_latency_ = kArmIntegerOpLatency;
1090 last_visited_latency_ = kArmIntegerOpLatency;
1091 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001092 case DataType::Type::kFloat32:
1093 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001094 // invokes runtime
1095 last_visited_internal_latency_ = kArmCallInternalLatency;
1096 break;
1097 default:
1098 last_visited_internal_latency_ = kArmIntegerOpLatency;
1099 last_visited_latency_ = kArmIntegerOpLatency;
1100 break;
1101 }
1102 break;
1103
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001104 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001105 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001106 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001107 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001108 case DataType::Type::kInt8:
1109 case DataType::Type::kUint16:
1110 case DataType::Type::kInt16:
1111 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001112 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1113 last_visited_latency_ = kArmFloatingPointOpLatency;
1114 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001115 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001116 // invokes runtime
1117 last_visited_internal_latency_ = kArmCallInternalLatency;
1118 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001119 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001120 last_visited_latency_ = kArmFloatingPointOpLatency;
1121 break;
1122 default:
1123 last_visited_latency_ = kArmFloatingPointOpLatency;
1124 break;
1125 }
1126 break;
1127
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001128 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001129 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001130 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001131 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001132 case DataType::Type::kInt8:
1133 case DataType::Type::kUint16:
1134 case DataType::Type::kInt16:
1135 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001136 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1137 last_visited_latency_ = kArmFloatingPointOpLatency;
1138 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001139 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001140 last_visited_internal_latency_ = 5 * kArmFloatingPointOpLatency;
1141 last_visited_latency_ = kArmFloatingPointOpLatency;
1142 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001143 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001144 last_visited_latency_ = kArmFloatingPointOpLatency;
1145 break;
1146 default:
1147 last_visited_latency_ = kArmFloatingPointOpLatency;
1148 break;
1149 }
1150 break;
1151
1152 default:
1153 last_visited_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1154 break;
1155 }
1156}
1157
xueliang.zhongf7caf682017-03-01 16:07:02 +00001158} // namespace arm
1159} // namespace art