blob: b3c8f105d1a9683b2d4caa1afb2f24e6167c0f5e [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:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100517 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100518 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100519 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100520 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100521 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000522 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
523 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100524 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000525 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency + 3 * kArmBranchLatency;
526 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100527 case DataType::Type::kFloat32:
528 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000529 last_visited_internal_latency_ = kArmIntegerOpLatency + 2 * kArmFloatingPointOpLatency;
530 break;
531 default:
532 last_visited_internal_latency_ = 2 * kArmIntegerOpLatency;
533 break;
534 }
535 last_visited_latency_ = kArmIntegerOpLatency;
536}
537
538void SchedulingLatencyVisitorARM::VisitBitwiseNegatedRight(HBitwiseNegatedRight* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100539 if (instruction->GetResultType() == DataType::Type::kInt32) {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000540 last_visited_latency_ = kArmIntegerOpLatency;
541 } else {
542 last_visited_internal_latency_ = kArmIntegerOpLatency;
543 last_visited_latency_ = kArmIntegerOpLatency;
544 }
545}
546
547void SchedulingLatencyVisitorARM::HandleGenerateDataProcInstruction(bool internal_latency) {
548 if (internal_latency) {
549 last_visited_internal_latency_ += kArmIntegerOpLatency;
550 } else {
551 last_visited_latency_ = kArmDataProcWithShifterOpLatency;
552 }
553}
554
555void SchedulingLatencyVisitorARM::HandleGenerateDataProc(HDataProcWithShifterOp* instruction) {
556 const HInstruction::InstructionKind kind = instruction->GetInstrKind();
557 if (kind == HInstruction::kAdd) {
558 last_visited_internal_latency_ = kArmIntegerOpLatency;
559 last_visited_latency_ = kArmIntegerOpLatency;
560 } else if (kind == HInstruction::kSub) {
561 last_visited_internal_latency_ = kArmIntegerOpLatency;
562 last_visited_latency_ = kArmIntegerOpLatency;
563 } else {
564 HandleGenerateDataProcInstruction(/* internal_latency */ true);
565 HandleGenerateDataProcInstruction();
566 }
567}
568
569void SchedulingLatencyVisitorARM::HandleGenerateLongDataProc(HDataProcWithShifterOp* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100570 DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
xueliang.zhongf7caf682017-03-01 16:07:02 +0000571 DCHECK(HDataProcWithShifterOp::IsShiftOp(instruction->GetOpKind()));
572
573 const uint32_t shift_value = instruction->GetShiftAmount();
574 const HInstruction::InstructionKind kind = instruction->GetInstrKind();
575
576 if (shift_value >= 32) {
577 // Different shift types actually generate similar code here,
578 // no need to differentiate shift types like the codegen pass does,
579 // which also avoids handling shift types from different ARM backends.
580 HandleGenerateDataProc(instruction);
581 } else {
582 DCHECK_GT(shift_value, 1U);
583 DCHECK_LT(shift_value, 32U);
584
585 if (kind == HInstruction::kOr || kind == HInstruction::kXor) {
586 HandleGenerateDataProcInstruction(/* internal_latency */ true);
587 HandleGenerateDataProcInstruction(/* internal_latency */ true);
588 HandleGenerateDataProcInstruction();
589 } else {
590 last_visited_internal_latency_ += 2 * kArmIntegerOpLatency;
591 HandleGenerateDataProc(instruction);
592 }
593 }
594}
595
596void SchedulingLatencyVisitorARM::VisitDataProcWithShifterOp(HDataProcWithShifterOp* instruction) {
597 const HDataProcWithShifterOp::OpKind op_kind = instruction->GetOpKind();
598
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100599 if (instruction->GetType() == DataType::Type::kInt32) {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000600 HandleGenerateDataProcInstruction();
601 } else {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100602 DCHECK_EQ(instruction->GetType(), DataType::Type::kInt64);
xueliang.zhongf7caf682017-03-01 16:07:02 +0000603 if (HDataProcWithShifterOp::IsExtensionOp(op_kind)) {
604 HandleGenerateDataProc(instruction);
605 } else {
606 HandleGenerateLongDataProc(instruction);
607 }
608 }
609}
610
611void SchedulingLatencyVisitorARM::VisitIntermediateAddress(HIntermediateAddress* ATTRIBUTE_UNUSED) {
612 // Although the code generated is a simple `add` instruction, we found through empirical results
613 // that spacing it from its use in memory accesses was beneficial.
614 last_visited_internal_latency_ = kArmNopLatency;
615 last_visited_latency_ = kArmIntegerOpLatency;
616}
617
Artem Serovf0fc4c62017-05-03 15:07:15 +0100618void SchedulingLatencyVisitorARM::VisitIntermediateAddressIndex(
619 HIntermediateAddressIndex* ATTRIBUTE_UNUSED) {
620 UNIMPLEMENTED(FATAL) << "IntermediateAddressIndex is not implemented for ARM";
621}
622
xueliang.zhongf7caf682017-03-01 16:07:02 +0000623void SchedulingLatencyVisitorARM::VisitMultiplyAccumulate(HMultiplyAccumulate* ATTRIBUTE_UNUSED) {
624 last_visited_latency_ = kArmMulIntegerLatency;
625}
626
627void SchedulingLatencyVisitorARM::VisitArrayGet(HArrayGet* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100628 DataType::Type type = instruction->GetType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000629 const bool maybe_compressed_char_at =
630 mirror::kUseStringCompression && instruction->IsStringCharAt();
631 HInstruction* array_instr = instruction->GetArray();
632 bool has_intermediate_address = array_instr->IsIntermediateAddress();
633 HInstruction* index = instruction->InputAt(1);
634
635 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100636 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100637 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100638 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100639 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100640 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100641 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000642 if (maybe_compressed_char_at) {
643 last_visited_internal_latency_ += kArmMemoryLoadLatency;
644 }
645 if (index->IsConstant()) {
646 if (maybe_compressed_char_at) {
647 last_visited_internal_latency_ +=
648 kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
649 last_visited_latency_ = kArmBranchLatency;
650 } else {
651 last_visited_latency_ += kArmMemoryLoadLatency;
652 }
653 } else {
654 if (has_intermediate_address) {
655 } else {
656 last_visited_internal_latency_ += kArmIntegerOpLatency;
657 }
658 if (maybe_compressed_char_at) {
659 last_visited_internal_latency_ +=
660 kArmIntegerOpLatency + kArmBranchLatency + kArmMemoryLoadLatency;
661 last_visited_latency_ = kArmBranchLatency;
662 } else {
663 last_visited_latency_ += kArmMemoryLoadLatency;
664 }
665 }
666 break;
667 }
668
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100669 case DataType::Type::kReference: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000670 if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
671 last_visited_latency_ = kArmLoadWithBakerReadBarrierLatency;
672 } else {
673 if (index->IsConstant()) {
674 last_visited_latency_ = kArmMemoryLoadLatency;
675 } else {
676 if (has_intermediate_address) {
677 } else {
678 last_visited_internal_latency_ += kArmIntegerOpLatency;
679 }
680 last_visited_internal_latency_ = kArmMemoryLoadLatency;
681 }
682 }
683 break;
684 }
685
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100686 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000687 if (index->IsConstant()) {
688 last_visited_latency_ = kArmMemoryLoadLatency;
689 } else {
690 last_visited_internal_latency_ += kArmIntegerOpLatency;
691 last_visited_latency_ = kArmMemoryLoadLatency;
692 }
693 break;
694 }
695
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100696 case DataType::Type::kFloat32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000697 if (index->IsConstant()) {
698 last_visited_latency_ = kArmMemoryLoadLatency;
699 } else {
700 last_visited_internal_latency_ += kArmIntegerOpLatency;
701 last_visited_latency_ = kArmMemoryLoadLatency;
702 }
703 break;
704 }
705
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100706 case DataType::Type::kFloat64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000707 if (index->IsConstant()) {
708 last_visited_latency_ = kArmMemoryLoadLatency;
709 } else {
710 last_visited_internal_latency_ += kArmIntegerOpLatency;
711 last_visited_latency_ = kArmMemoryLoadLatency;
712 }
713 break;
714 }
715
716 default:
717 LOG(FATAL) << "Unreachable type " << type;
718 UNREACHABLE();
719 }
720}
721
722void SchedulingLatencyVisitorARM::VisitArrayLength(HArrayLength* instruction) {
723 last_visited_latency_ = kArmMemoryLoadLatency;
724 if (mirror::kUseStringCompression && instruction->IsStringLength()) {
725 last_visited_internal_latency_ = kArmMemoryLoadLatency;
726 last_visited_latency_ = kArmIntegerOpLatency;
727 }
728}
729
730void SchedulingLatencyVisitorARM::VisitArraySet(HArraySet* instruction) {
731 HInstruction* index = instruction->InputAt(1);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100732 DataType::Type value_type = instruction->GetComponentType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000733 HInstruction* array_instr = instruction->GetArray();
734 bool has_intermediate_address = array_instr->IsIntermediateAddress();
735
736 switch (value_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100737 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100738 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100739 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100740 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100741 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100742 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000743 if (index->IsConstant()) {
744 last_visited_latency_ = kArmMemoryStoreLatency;
745 } else {
746 if (has_intermediate_address) {
747 } else {
748 last_visited_internal_latency_ = kArmIntegerOpLatency;
749 }
750 last_visited_latency_ = kArmMemoryStoreLatency;
751 }
752 break;
753 }
754
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100755 case DataType::Type::kReference: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000756 if (instruction->InputAt(2)->IsNullConstant()) {
757 if (index->IsConstant()) {
758 last_visited_latency_ = kArmMemoryStoreLatency;
759 } else {
760 last_visited_internal_latency_ = kArmIntegerOpLatency;
761 last_visited_latency_ = kArmMemoryStoreLatency;
762 }
763 } else {
764 // Following the exact instructions of runtime type checks is too complicated,
765 // just giving it a simple slow latency.
766 last_visited_latency_ = kArmRuntimeTypeCheckLatency;
767 }
768 break;
769 }
770
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100771 case DataType::Type::kInt64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000772 if (index->IsConstant()) {
773 last_visited_latency_ = kArmMemoryLoadLatency;
774 } else {
775 last_visited_internal_latency_ = kArmIntegerOpLatency;
776 last_visited_latency_ = kArmMemoryLoadLatency;
777 }
778 break;
779 }
780
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100781 case DataType::Type::kFloat32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000782 if (index->IsConstant()) {
783 last_visited_latency_ = kArmMemoryLoadLatency;
784 } else {
785 last_visited_internal_latency_ = kArmIntegerOpLatency;
786 last_visited_latency_ = kArmMemoryLoadLatency;
787 }
788 break;
789 }
790
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100791 case DataType::Type::kFloat64: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000792 if (index->IsConstant()) {
793 last_visited_latency_ = kArmMemoryLoadLatency;
794 } else {
795 last_visited_internal_latency_ = kArmIntegerOpLatency;
796 last_visited_latency_ = kArmMemoryLoadLatency;
797 }
798 break;
799 }
800
801 default:
802 LOG(FATAL) << "Unreachable type " << value_type;
803 UNREACHABLE();
804 }
805}
806
807void SchedulingLatencyVisitorARM::VisitBoundsCheck(HBoundsCheck* ATTRIBUTE_UNUSED) {
808 last_visited_internal_latency_ = kArmIntegerOpLatency;
809 // Users do not use any data results.
810 last_visited_latency_ = 0;
811}
812
813void SchedulingLatencyVisitorARM::HandleDivRemConstantIntegralLatencies(int32_t imm) {
814 if (imm == 0) {
815 last_visited_internal_latency_ = 0;
816 last_visited_latency_ = 0;
817 } else if (imm == 1 || imm == -1) {
818 last_visited_latency_ = kArmIntegerOpLatency;
819 } else if (IsPowerOfTwo(AbsOrMin(imm))) {
820 last_visited_internal_latency_ = 3 * kArmIntegerOpLatency;
821 last_visited_latency_ = kArmIntegerOpLatency;
822 } else {
823 last_visited_internal_latency_ = kArmMulIntegerLatency + 2 * kArmIntegerOpLatency;
824 last_visited_latency_ = kArmIntegerOpLatency;
825 }
826}
827
828void SchedulingLatencyVisitorARM::VisitDiv(HDiv* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100829 DataType::Type type = instruction->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000830 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100831 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000832 HInstruction* rhs = instruction->GetRight();
833 if (rhs->IsConstant()) {
834 int32_t imm = Int32ConstantFrom(rhs->AsConstant());
835 HandleDivRemConstantIntegralLatencies(imm);
836 } else {
837 last_visited_latency_ = kArmDivIntegerLatency;
838 }
839 break;
840 }
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100841 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000842 last_visited_latency_ = kArmDivFloatLatency;
843 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100844 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000845 last_visited_latency_ = kArmDivDoubleLatency;
846 break;
847 default:
848 last_visited_internal_latency_ = kArmCallInternalLatency;
849 last_visited_latency_ = kArmCallLatency;
850 break;
851 }
852}
853
854void SchedulingLatencyVisitorARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
855 HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
856}
857
858void SchedulingLatencyVisitorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
859 HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
860}
861
862void SchedulingLatencyVisitorARM::VisitInstanceOf(HInstanceOf* ATTRIBUTE_UNUSED) {
863 last_visited_internal_latency_ = kArmCallInternalLatency;
864 last_visited_latency_ = kArmIntegerOpLatency;
865}
866
867void SchedulingLatencyVisitorARM::VisitInvoke(HInvoke* ATTRIBUTE_UNUSED) {
868 last_visited_internal_latency_ = kArmCallInternalLatency;
869 last_visited_latency_ = kArmCallLatency;
870}
871
872void SchedulingLatencyVisitorARM::VisitLoadString(HLoadString* ATTRIBUTE_UNUSED) {
873 last_visited_internal_latency_ = kArmLoadStringInternalLatency;
874 last_visited_latency_ = kArmMemoryLoadLatency;
875}
876
877void SchedulingLatencyVisitorARM::VisitNewArray(HNewArray* ATTRIBUTE_UNUSED) {
878 last_visited_internal_latency_ = kArmIntegerOpLatency + kArmCallInternalLatency;
879 last_visited_latency_ = kArmCallLatency;
880}
881
882void SchedulingLatencyVisitorARM::VisitNewInstance(HNewInstance* instruction) {
883 if (instruction->IsStringAlloc()) {
884 last_visited_internal_latency_ = 2 * kArmMemoryLoadLatency + kArmCallInternalLatency;
885 } else {
886 last_visited_internal_latency_ = kArmCallInternalLatency;
887 }
888 last_visited_latency_ = kArmCallLatency;
889}
890
891void SchedulingLatencyVisitorARM::VisitRem(HRem* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100892 DataType::Type type = instruction->GetResultType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000893 switch (type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100894 case DataType::Type::kInt32: {
xueliang.zhongf7caf682017-03-01 16:07:02 +0000895 HInstruction* rhs = instruction->GetRight();
896 if (rhs->IsConstant()) {
897 int32_t imm = Int32ConstantFrom(rhs->AsConstant());
898 HandleDivRemConstantIntegralLatencies(imm);
899 } else {
900 last_visited_internal_latency_ = kArmDivIntegerLatency;
901 last_visited_latency_ = kArmMulIntegerLatency;
902 }
903 break;
904 }
905 default:
906 last_visited_internal_latency_ = kArmCallInternalLatency;
907 last_visited_latency_ = kArmCallLatency;
908 break;
909 }
910}
911
912void SchedulingLatencyVisitorARM::HandleFieldGetLatencies(HInstruction* instruction,
913 const FieldInfo& field_info) {
914 DCHECK(instruction->IsInstanceFieldGet() || instruction->IsStaticFieldGet());
915 DCHECK(codegen_ != nullptr);
916 bool is_volatile = field_info.IsVolatile();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100917 DataType::Type field_type = field_info.GetFieldType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000918 bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
919
920 switch (field_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100921 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100922 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100923 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100924 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100925 case DataType::Type::kInt16:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100926 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000927 last_visited_latency_ = kArmMemoryLoadLatency;
928 break;
929
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100930 case DataType::Type::kReference:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000931 if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
932 last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
933 last_visited_latency_ = kArmMemoryLoadLatency;
934 } else {
935 last_visited_latency_ = kArmMemoryLoadLatency;
936 }
937 break;
938
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100939 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000940 if (is_volatile && !atomic_ldrd_strd) {
941 last_visited_internal_latency_ = kArmMemoryLoadLatency + kArmIntegerOpLatency;
942 last_visited_latency_ = kArmMemoryLoadLatency;
943 } else {
944 last_visited_latency_ = kArmMemoryLoadLatency;
945 }
946 break;
947
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100948 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000949 last_visited_latency_ = kArmMemoryLoadLatency;
950 break;
951
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100952 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000953 if (is_volatile && !atomic_ldrd_strd) {
954 last_visited_internal_latency_ =
955 kArmMemoryLoadLatency + kArmIntegerOpLatency + kArmMemoryLoadLatency;
956 last_visited_latency_ = kArmIntegerOpLatency;
957 } else {
958 last_visited_latency_ = kArmMemoryLoadLatency;
959 }
960 break;
961
962 default:
963 last_visited_latency_ = kArmMemoryLoadLatency;
964 break;
965 }
966
967 if (is_volatile) {
968 last_visited_internal_latency_ += kArmMemoryBarrierLatency;
969 }
970}
971
972void SchedulingLatencyVisitorARM::HandleFieldSetLatencies(HInstruction* instruction,
973 const FieldInfo& field_info) {
974 DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
975 DCHECK(codegen_ != nullptr);
976 bool is_volatile = field_info.IsVolatile();
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100977 DataType::Type field_type = field_info.GetFieldType();
xueliang.zhongf7caf682017-03-01 16:07:02 +0000978 bool needs_write_barrier =
979 CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1));
980 bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
981
982 switch (field_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100983 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100984 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100985 case DataType::Type::kInt8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100986 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +0100987 case DataType::Type::kInt16:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000988 if (is_volatile) {
989 last_visited_internal_latency_ = kArmMemoryBarrierLatency + kArmMemoryStoreLatency;
990 last_visited_latency_ = kArmMemoryBarrierLatency;
991 } else {
992 last_visited_latency_ = kArmMemoryStoreLatency;
993 }
994 break;
995
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100996 case DataType::Type::kInt32:
997 case DataType::Type::kReference:
xueliang.zhongf7caf682017-03-01 16:07:02 +0000998 if (kPoisonHeapReferences && needs_write_barrier) {
999 last_visited_internal_latency_ += kArmIntegerOpLatency * 2;
1000 }
1001 last_visited_latency_ = kArmMemoryStoreLatency;
1002 break;
1003
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001004 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001005 if (is_volatile && !atomic_ldrd_strd) {
1006 last_visited_internal_latency_ =
1007 kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1008 last_visited_latency_ = kArmIntegerOpLatency;
1009 } else {
1010 last_visited_latency_ = kArmMemoryStoreLatency;
1011 }
1012 break;
1013
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001014 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001015 last_visited_latency_ = kArmMemoryStoreLatency;
1016 break;
1017
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001018 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001019 if (is_volatile && !atomic_ldrd_strd) {
1020 last_visited_internal_latency_ = kArmIntegerOpLatency +
1021 kArmIntegerOpLatency + kArmMemoryLoadLatency + kArmMemoryStoreLatency;
1022 last_visited_latency_ = kArmIntegerOpLatency;
1023 } else {
1024 last_visited_latency_ = kArmMemoryStoreLatency;
1025 }
1026 break;
1027
1028 default:
1029 last_visited_latency_ = kArmMemoryStoreLatency;
1030 break;
1031 }
1032}
1033
1034void SchedulingLatencyVisitorARM::VisitStaticFieldGet(HStaticFieldGet* instruction) {
1035 HandleFieldGetLatencies(instruction, instruction->GetFieldInfo());
1036}
1037
1038void SchedulingLatencyVisitorARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
1039 HandleFieldSetLatencies(instruction, instruction->GetFieldInfo());
1040}
1041
1042void SchedulingLatencyVisitorARM::VisitSuspendCheck(HSuspendCheck* instruction) {
1043 HBasicBlock* block = instruction->GetBlock();
1044 DCHECK((block->GetLoopInformation() != nullptr) ||
1045 (block->IsEntryBlock() && instruction->GetNext()->IsGoto()));
1046 // Users do not use any data results.
1047 last_visited_latency_ = 0;
1048}
1049
1050void SchedulingLatencyVisitorARM::VisitTypeConversion(HTypeConversion* instr) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001051 DataType::Type result_type = instr->GetResultType();
1052 DataType::Type input_type = instr->GetInputType();
xueliang.zhongf7caf682017-03-01 16:07:02 +00001053
1054 switch (result_type) {
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001055 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001056 case DataType::Type::kInt8:
1057 case DataType::Type::kUint16:
1058 case DataType::Type::kInt16:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001059 last_visited_latency_ = kArmIntegerOpLatency; // SBFX or UBFX
1060 break;
1061
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001062 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001063 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001064 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001065 last_visited_latency_ = kArmIntegerOpLatency; // MOV
1066 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001067 case DataType::Type::kFloat32:
1068 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001069 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1070 last_visited_latency_ = kArmFloatingPointOpLatency;
1071 break;
1072 default:
1073 last_visited_latency_ = kArmIntegerOpLatency;
1074 break;
1075 }
1076 break;
1077
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001078 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001079 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001080 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001081 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001082 case DataType::Type::kInt8:
1083 case DataType::Type::kUint16:
1084 case DataType::Type::kInt16:
1085 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001086 // MOV and extension
1087 last_visited_internal_latency_ = kArmIntegerOpLatency;
1088 last_visited_latency_ = kArmIntegerOpLatency;
1089 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001090 case DataType::Type::kFloat32:
1091 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001092 // invokes runtime
1093 last_visited_internal_latency_ = kArmCallInternalLatency;
1094 break;
1095 default:
1096 last_visited_internal_latency_ = kArmIntegerOpLatency;
1097 last_visited_latency_ = kArmIntegerOpLatency;
1098 break;
1099 }
1100 break;
1101
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001102 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001103 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001104 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001105 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001106 case DataType::Type::kInt8:
1107 case DataType::Type::kUint16:
1108 case DataType::Type::kInt16:
1109 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001110 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1111 last_visited_latency_ = kArmFloatingPointOpLatency;
1112 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001113 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001114 // invokes runtime
1115 last_visited_internal_latency_ = kArmCallInternalLatency;
1116 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001117 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001118 last_visited_latency_ = kArmFloatingPointOpLatency;
1119 break;
1120 default:
1121 last_visited_latency_ = kArmFloatingPointOpLatency;
1122 break;
1123 }
1124 break;
1125
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001126 case DataType::Type::kFloat64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001127 switch (input_type) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001128 case DataType::Type::kBool:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001129 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001130 case DataType::Type::kInt8:
1131 case DataType::Type::kUint16:
1132 case DataType::Type::kInt16:
1133 case DataType::Type::kInt32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001134 last_visited_internal_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1135 last_visited_latency_ = kArmFloatingPointOpLatency;
1136 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001137 case DataType::Type::kInt64:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001138 last_visited_internal_latency_ = 5 * kArmFloatingPointOpLatency;
1139 last_visited_latency_ = kArmFloatingPointOpLatency;
1140 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001141 case DataType::Type::kFloat32:
xueliang.zhongf7caf682017-03-01 16:07:02 +00001142 last_visited_latency_ = kArmFloatingPointOpLatency;
1143 break;
1144 default:
1145 last_visited_latency_ = kArmFloatingPointOpLatency;
1146 break;
1147 }
1148 break;
1149
1150 default:
1151 last_visited_latency_ = kArmTypeConversionFloatingPointIntegerLatency;
1152 break;
1153 }
1154}
1155
xueliang.zhongf7caf682017-03-01 16:07:02 +00001156} // namespace arm
1157} // namespace art